views:

103

answers:

2

Hi all, 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":

  • a.getId() -> current new id OK
  • a.getBList() -> still null...

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..

+1  A: 

Oh... ok

session.refresh(a);

This work good... is this the solution, isn't true?

blow
@blow Blow, Here http://docs.jboss.org/hibernate/core/3.3/reference/en/html/objectstate.html#objectstate-transitive you can get a good insight about which persistence method To use when using cascading
Arthur Ronald F D Garcia
+3  A: 

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:

Pascal Thivent
thank you Pascal
blow
@blow: You're welcome.
Pascal Thivent
update..........
blow
@blow: Please post this as a new question, this is really a different topic.
Pascal Thivent
Thank you for advice, my new question si here http://stackoverflow.com/questions/3077278/hibernate-batch-update-returned-unexpected-row-count-from-update
blow