当前位置: 首页 > 面试题库 >

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

汤弘文
2023-03-14
问题内容

我有一个关于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中的错误。令人惊讶的是,尚未报告,请随时进行报告。

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

作为解决方法,您可以flush()在保留孩子之后进行会话:

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


 类似资料:
  • 问题内容: 我有一个由以下映射的关联: 我想使用Criteria API返回所有包含一个或多个带有attribute实体的实体的列表。我不希望映射集合被查询过滤。 例如,给出以下内容: 该查询应返回以下内容: 到目前为止,我正在使用以下条件查询: 然而,它返回的等价于 即,它为每个子元素返回一个父记录(填充了子集合) 有谁知道在这种情况下如何仅返回唯一的父元素? 意见表示赞赏,p。 问题答案: 您

  • 我有一个父实体,与其子实体有OneToMany关联: 当我调用方法时,Hibernate不验证children集合@size约束,并按原样保留child“,这导致数据库中的实体无效。 为什么Hibernate不验证父实体?

  • 在Java集合中,哪个集合不允许重复,哪个集合还保留数据的插入顺序?

  • 问题内容: 我与CohortGroup和Employee有很多关系。每当我将Employee插入CohortGroup时,hibernate都会从解析表中删除该组,然后再次插入所有成员以及新成员。为什么不只是添加新的呢? 组中的注释: 员工的另一边 代码嗅探 下面是日志中报告的SQL 这种接缝的效率很低,并且会引起一些问题。如果有人提出要求将雇员添加到组中,则有些人将其改写。 诸如equals和h

  • 我在Hibernate(4.3.0)中遇到了一个问题,其中as单向@OneToMany返回重复项。 我的数据库结构(MySQL与InnoDB),其中作为“条目”表与“entry_address”表有1: N关系。“条目”表是主表,“entry_address”是“条目”表的子表。 下面是“entry”实体的最小代码。 以下是“entry_address”实体的最小代码: 这是Hibernate完成

  • 我一直在寻找一个解决方案,以最好地实现一个不插入,如果行已经存在。我读过很多不同的答案,我觉得有点超出我的水平。 例如,下面的文章是最大的结果:SQL Server Insert如果不存在,但我不明白为什么要使用这些变量,以及如何定义table1和Table2。有人能进一步解释一下吗,这样我就可以把它应用到我的情况中了?