Hibernate 将重复项插入到 @OneToMany 集合中

标签 hibernate jpa-2.0 one-to-many

我有一个关于 Hibernate 3.6.7 和 JPA 2.0 的问题。

考虑以下实体(为简洁起见,省略了一些 getter 和 setter):

@Entity
public class Parent {
    @Id
    @GeneratedValue
    private int id;

    @OneToMany(mappedBy="parent")
    private List<Child> children = new LinkedList<Child>();

    @Override
    public boolean equals(Object obj) {
        return id == ((Parent)obj).id;
    }

    @Override
    public int hashCode() {
        return id;
    }
}

@Entity
public class Child {
    @Id
    @GeneratedValue
    private int id;

    @ManyToOne
    private Parent parent;

    public void setParent(Parent parent) {
        this.parent = parent;
    }

    @Override
    public boolean equals(Object obj) {
        return id == ((Child)obj).id;
    }

    @Override
    public int hashCode() {
        return id;
    }
}

现在考虑这段代码:
// persist parent entity in a transaction

EntityManager em = emf.createEntityManager();
em.getTransaction().begin();

Parent parent = new Parent();
em.persist(parent);
int id = parent.getId();

em.getTransaction().commit();
em.close();

// relate and persist child entity in a new transaction

em = emf.createEntityManager();
em.getTransaction().begin();

parent = em.find(Parent.class, id);
// *: parent.getChildren().size();
Child child = new Child();
child.setParent(parent);
parent.getChildren().add(child);
em.persist(child);

System.out.println(parent.getChildren()); // -> [Child@1, Child@1]

em.getTransaction().commit();
em.close();

子实体被错误地插入到父实体的子列表中两次。

执行以下操作之一时,代码可以正常工作(列表中没有重复条目):
  • 删除 mappedBy父实体中的属性
  • 对子列表执行一些读取操作(例如,取消注释由 * 标记的行)

  • 这显然是一种非常奇怪的行为。此外,当使用 EclipseLink 作为持久性提供程序时,代码按预期工作(没有重复)。

    这是一个 hibernate 错误还是我错过了什么?

    谢谢

    最佳答案

    这是 hibernate 中的一个错误。令人惊讶的是,它还没有被报道,feel free to report it .

    针对未初始化的惰性集合的操作被排队以便在集合初始化后执行它们,当这些操作与数据库中的数据发生冲突时,Hibernate 不会处理这种情况。通常这不是问题,因为该队列在 flush() 时被清除。 ,并且可能的冲突更改会在 flush() 上传播到数据库。也是。但是,某些更改(例如持久化具有由 IDENTITY 类型的生成器生成的 ID 的实体,我猜,这是您的情况)在没有完整 flush() 的情况下传播到数据库。 ,在这些情况下,冲突是可能的。

    作为一种解决方法,您可以 flush()坚持 child 后的 session :

    em.persist(child); 
    em.flush();
    

    关于Hibernate 将重复项插入到 @OneToMany 集合中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7903800/

    相关文章:

    java - Spring 数据 : DeleteAll and Insert in same transaction

    Java Stream 与 JPA 一对多(LAZY)关系不起作用

    java - 如何更改 Hibernate4 中的日志记录级别?

    java - JPA 字符映射

    java - JPA (Hibernate) 不会增加版本列

    java - 使用 JPA 时出现“java.lang.NoSuchFieldError”

    mysql group by with where 返回完全其他结果

    postgresql - 减少对包含实体的 JPQL POJO 的查询次数

    FFMPEG 来自 BlackMagic 输入的多个输出

    java - 如何避免 hibernate 中的脏检查