【问题标题】:Update OneToMany list after entity save in Hibernate在休眠中保存实体后更新 OneToMany 列表
【发布时间】:2010-06-19 18:15:09
【问题描述】:

我有关系:

// 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() -> 当前新 id 正常
  • a.getBList() -> 仍然为空...

那么,为什么在这种情况下 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 才能正确重新加载 A 实例?


更新

我有这个例外

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

当我从中删除 b 后尝试保存或更新实体 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) 问题又解决了……那么,正确的方法是什么? 我知道......我完全不喜欢休眠......

【问题讨论】:

    标签: java hibernate orm


    【解决方案1】:

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

    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 教程中对此进行了讨论:

    【讨论】:

    【解决方案2】:

    哦...好的

    session.refresh(a);
    

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

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-03-16
    • 1970-01-01
    • 1970-01-01
    • 2012-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多