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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3076677/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 00:15:30  来源:igfitidea点击:

Update OneToMany list after entity save in Hibernate

javahibernateorm

提问by blow

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...
  • a.getId() -> 当前新 ID OK
  • a.getBList() -> 仍然为空...

So, why bList is not update in this case?

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

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.

但是loadedA 仍然有一个像a 一样的NULL bList。

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?

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



UPDATE

更新

I have this exception

我有这个例外

StaleStateException: Batch update returned unexpected row count from update

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

when i try to saveOrUpdate entity a after deleting b from it.

当我在删除 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

this two operation are not in the same method of course, are fired by gui event.

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

session.clear is the real solution? Im doing (probably) wrong?

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

update

更新

removing session.delete(b) the problem is solved again... so, what is the corretc way? I know...im totally noob with hibernate..

删除 session.delete(b) 问题又解决了……那么,正确的方法是什么?我知道......我完全是冬眠的菜鸟..

采纳答案by blow

Oh... ok

哦好的

session.refresh(a);

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

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

回答by Pascal Thivent

When working with bi-directional associations, you have to set the link on bothsides 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:

这在 Hibernate 教程中讨论过: