i have relationship:
// In A.java class
@OneToMany(mappedBy="a", fetch=FetchType.LAZY)
@Cascade(CascadeType.SAVE_UPDATE)
private List<B> bList;
// In B.java class
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="id_a")
@Cascade(CascadeType.SAVE_UPDATE)
private A a;
Now look this:
A a=new A();
// setting A
B b=new B();
// setting B
b.setA(a);
session.save(b); // this save b and a obviously
Now the "problem":
So, why bList is not update in this case?
I tried to reload a after save, in this way:
A a=new A();
// setting A
B b=new B();
// setting B
b.setA(a);
session.save(b);
A loadedA=(A)session.get(A, a.getId());
But loadedA still have a NULL bList like a.
Naturally to avoid this problem i do in thy way:
A a=new A();
// setting A
B b=new B();
// setting B
List<B> bList=new ArrayList<B>();
bList.add(b);
a.setBList(bList);
session.save(a); // this save a and b
In this way all work good, but my question is: Why Id is correctly update after save operation and bList no? I have to query db with a select statement to reload A instance correctly?
UPDATE
I have this exception
StaleStateException: Batch update returned unexpected row count from update
when i try to saveOrUpdate entity a after deleting b from it.
// first delete old b record
Session session=HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
a.getBList().remove(b);
b.setA(null);
session.delete(b);
// session.clear(); // this would solve my problem, but is it correct??
session.getTransaction().commit();
// then insert new b record
Session session=HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
B b=new B();
a.getBList().add(b);
b.setA(a);
session.saveOrUpdate(a);
session.getTransaction().commit(); // this throw exception
this two operation are not in the same method of course, are fired by gui event.
session.clear is the real solution? Im doing (probably) wrong?
update
removing session.delete(b) the problem is solved again... so, what is the corretc way? I know...im totally noob with hibernate..
When working with bi-directional associations, you have to set the link on both sides of the association:
A a = new A();
B b = new B();
a.getBList().add(b);
b.setA(a);
session.persist(b);
And actually, the common pattern is to implement defensive link management methods like this:
public class A {
@OneToMany(mappedBy="a", fetch=FetchType.LAZY)
@Cascade(CascadeType.SAVE_UPDATE)
private List<B> bList = new ArrayList<B>();
protected List<B> getListB() {
return bList;
}
protected void setListB(List bList) {
this.bList = bList;
}
public void addBToBs(B b) {
bList.add(b);
b.setA(this);
}
//...
}
And the code becomes:
A a = new A();
B b = new B();
a.addBToBs(b);
session.persist(b);
This is discussed in the Hibernate Tutorial:
Oh... ok
session.refresh(a);
This work good... is this the solution, isn't true?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With