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

标签 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() -> 当前新id OK
  • 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 仍然有一个像 a 的 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

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


更新

我有这个异常(exception)

StaleStateException: Batch update returned unexpected row count from update

当我尝试在从中删除 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) 问题又解决了... 那么,正确的方法是什么? 我知道...我对 hibernate 完全是菜鸟..

最佳答案

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

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

关于java - 在 Hibernate 中保存实体后更新 OneToMany 列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3076677/

相关文章:

java - 根据时间值返回不同的值

java - 如何让 Gradle 编译使用较新 Java 版本的源库?

java - SQL 序列 : Hibernate and Liquibase

java - 一对多关系时使用 spring 存储库获取数据

java - spring 4和hibernate 5集成: could not obtain transaction-synchronized Session for current thread

c# - 小巧玲珑的查询(..): stream or loads all?

java - hibernate 中的 @Embedded 注释对我不起作用

Django ORM - 使用 M2M 加速过滤器

javascript - 如何在 Node.js 网站中组织模型?

java - 线程通过调用interrupt()被中断,但是Thread.isInterrupted()返回false