在Hibernate中实体保存后更新OneToMany列表

blo*_*low 7 java orm hibernate

我有关系:

// 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;
Run Code Online (Sandbox Code Playgroud)

现在看看这个:

A a=new A();
// setting A

B b=new B();
// setting B
b.setA(a);

session.save(b); // this save b and a obviously
Run Code Online (Sandbox Code Playgroud)

现在的"问题":

  • a.getId() - >当前的新ID OK
  • a.getBList() - >仍为null ...

那么,为什么bList在这种情况下不更新?

我尝试以这种方式重新加载后保存:

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());
Run Code Online (Sandbox Code Playgroud)

但loadedA仍然有一个像b的NULL bList.

我自然会以你的方式避免这个问题:

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
Run Code Online (Sandbox Code Playgroud)

这样一切工作都很好,但我的问题是:为什么Id在保存操作后正确更新而bList没有?我必须使用select语句查询db以正确地重新加载实例?


UPDATE

我有这个例外

StaleStateException:批量更新从更新返回意外的行数

当我从中删除b后尝试saveOrUpdate实体a时.

// 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
Run Code Online (Sandbox Code Playgroud)

这两个操作当然不是同一种方法,都是由gui事件引发的.

session.clear是真正的解决方案吗?我做(可能)错了?

更新

删除session.delete(b)问题再次解决......那么,corretc方式是什么?我知道......我非常喜欢休眠...

Pas*_*ent 6

当双向协会的工作,你必须设置链接两个协会方面:

A a = new A();
B b = new B();
a.getBList().add(b);
b.setA(a);

session.persist(b);
Run Code Online (Sandbox Code Playgroud)

实际上,常见的模式是实现这样的防御性链接管理方法:

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);
    }

    //...
}
Run Code Online (Sandbox Code Playgroud)

代码变成:

A a = new A();
B b = new B();
a.addBToBs(b);

session.persist(b);
Run Code Online (Sandbox Code Playgroud)

这在Hibernate教程中讨论:


blo*_*low 4

哦好的

session.refresh(a);
Run Code Online (Sandbox Code Playgroud)

这工作很好......这是解决方案,不是吗?