Boa tarde pessoal!
Seguinte, em um mapeamento 1-N e N-1 eu crio um objeto X e atribuo a ele uma lista de novos objetos Y. neste momento nem X nem Y estão atachados. Ex:
X x = new X();
x.setNome( "XPTO" );
x.setListaDeY( this.retornaUmaListaDeY() );
// aqui manda salvar
meuDaoJpa.save( x );
Logo em seguida, ao tentar imprimir para cada Y o nome de X relacionado como abaixo,
for ( Y y : x.getListDeY ) {
// Aqui dá NPE
System.out.println( y.getX.getNome() );
}
está dando NPE. O que está errado?
Abaixo o mapeamento entre X e Y.
class X {
...
@OneToMany(mappedBy = "x", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private Set<Y> ys;
}
class Y {
...
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "CD_X")
private X x;
}
Experimenta executar um FLUSH na sessão, isso vai fazer com que a persistencia seja efetivada de fato. Inclusive deixe configurado para ele mostrar os sqls que estão sendo gerados para vc ver o que o ORM está fazendo.
flws
Olá fantomas.
fazendo o que você falou continua dando NPE.
Não sei se adianta mas eu estou utilizando Spring (JpaTemplate).
No método save do meu DAO eu adicionei o flush mas ainda dá NPE.
Méu método:
@Override
public T create(T obj) {
this.getJpaTemplate().persist(obj);
// Adicionei esta linha aqui
this.getJpaTemplate().flush();
return obj;
}
Quando eu seto x a cada y antes de atribuir a lista de y a x funciona direito mas eu acho que não era para ser necessário fazer isto para funcionar.
Tipo:
para cada y eu atribuo x e depois seto a lista de y em x. :roll:
Entendeu???..
Entendi…
A princípio também acho que deveria estar funcionando, como não vejo nada de muito óbvio no teu código…complicou. Mas mesmo assim vou dar dois chutes:
-
Você já deu uma olhada nos atributos da anotação @ManyToOne? Aqueles insertable, updatable etc…
-
No seu código vc apresentou o método x.setListaDeY( this.retornaUmaListaDeY() );, como é a implementação dele?
Se for igual a isto listaDeYs = variosYs; experimente trocar para uma implementação que adicione item a item (y a y) na lista. Isto porque a JPA / Hibernate troca o objeto do tipo lista para um tipo de lista dele dinamicamente ao gerar a instancia do objeto, talvez quando vc atribui diretamente uma instancia de outra lista que certamente não é do tipo que ele espera vc esteja “confundindo” os algoritimos dele. Faça um teste e analise com o debugger.
flws
fantomas, acho que a implementação do retornaUmaListaDeY() já está do jeito que você sugeriu. Segue:
protected Set<Y> getYs( ) {
Set<Y> ys = new HashSet<Y>();
for ( int x = 0; x < 12; x ++ ) {
Y y = new Y();
y.setName( "ABCD" );
ys.add(y);
}
return ys;
}
Agora se eu passar X e setar na lista de ys funciona. Segue:
protected Set<Y> getYs( X x ) {
Set<Y> ys = new HashSet<Y>();
for ( int x = 0; x < 12; x ++ ) {
Y y = new Y();
y.setName( "ABCD" );
// Assim funciona mas não acho certo
y.setX( x );
ys.add(y);
}
return ys;
}
vc não pode simplismente criar um Y, e adciona a lista de X … vc tem que dizer a Y na relação de N-1 a referencia de X …
sendo assim
X x = new X();
x.setNome( "XPTO" );
x.setListaDeY( this.retornaUmaListaDeY() );
// aqui manda salvar
meuDaoJpa.save( x );
o método setListaDeY teria que ser algo como
public void setListaDeY( Collection<Y> ys);
this.listaDeY = ys;
for (Y y : ys)
y.setX(this); // <== vc precisa avisar a Y, sobre sua ligação com X
}
ou vc faz nesse ponto, ou faz no momento que vai crair X …
eu particularmente não gosto de usar setListaDeY… eu uso métodos como
public void addY(Y y) {
this.getYs().add(y);
y.setX(this);
}
Entendi Lavieri.
Então o que eue achava que não era o correto é o correto.
Para cada y eu tenho que setar x e depois setar para x cada y correspondente.
Obrigado pessoal!!!