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

时间:2010-06-19 18:15:09

标签: java hibernate orm

我有关系:

// 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;

现在看看:

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

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

session.save(b); // this save b and a obviously

现在是“问题”:

  • a.getId() - &gt;当前的新ID好了
  • a.getBList() - &gt;仍然是空的......

那么,为什么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());

但loadedA仍然有一个NULL bList,如a。

当然,为了避免这个问题,我会以你的方式做到:

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

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


更新

我有这个例外

  

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

这两个操作当然不是同一个方法,是由gui事件触发的。

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

更新

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

2 个答案:

答案 0 :(得分:6)

使用双向关联时,您必须在关联的两个侧设置链接:

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

session.persist(b);

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

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

    //...
}

代码变为:

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

session.persist(b);

这在Hibernate教程中讨论:

答案 1 :(得分:4)

哦......好的

session.refresh(a);

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