java - EclipseLink 以一对多关系生成重复条目

标签 java jpa eclipselink one-to-many many-to-one

我正在使用 EclipseLink 2.4.1 和 JPA 2.0。在我的示例中,我有以下类定义:

@Entity
public class Shepard {
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;


    @OneToMany(mappedBy = "shepard", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private List<Sheep> sheeps;

    public void addSheep(Sheep sheep) {
        if (sheep != null) {
            if (sheeps == null) {
                sheeps = new ArrayList<>();
            }

            if (!sheeps.contains(sheep)) {
                sheeps.add(sheep);
            }
        }
    }
}

@Entity
public class Sheep {
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;

    @Column(name = "name")
    private String name;

    @ManyToOne(fetch = FetchType.EAGER, optional = false)
    @JoinColumn(name="shepard_id")
    private Shepard shepard;

    public Sheep(Shepard shepard, String name) {
        this.shepard = shepard;
        this.name = name;

        shepard.addSheep(this);
    }
}

现在,当我编写 Junit 测试并执行以下操作时。请注意,Sheep 构造函数调用 Shepard.addSheep(Sheep)!

EntityManagerFactory emf = Persistence.createEntityManagerFactory("data");
EnttyManager em = emf.createEntityManager();
Shepard shepard = new Shepard();

// I Persist Shepard
em.getTransaction().begin();
em.persist(shepard);
em.getTransaction().commit();

// II Persist Tilda
Sheep tilda = new Sheep(shepard, "Tilda");
em.getTransaction().begin();
em.persist(tilda);
em.getTransaction().commit();

// III Persist Martha via Shepard
Sheep martha = new Sheep(shepard, "Martha");
em.getTransaction().begin();
em.merge(shepard);
em.getTransaction().commit();

然后对 Sheep's 进行命名查询,我得到了“Tilda”的重复条目!

这不会发生,当我编码时

em.persist(martha);

改为作为最后一个实体管理器访问权限。

分析调试输出,我可以看到在II 之后有一个 [id=1] 的 Shepard 对象和一个 [id=1] 的 Sheep 对象。 在 III 之前和之后,Shepard 持有两个关于 Sheeps 的引用文献,之前是 [id=1] 是 Tilda,[id=null] 是 Martha。 在 III 之后,Shepard 持有两份关于绵羊的引用资料,Tilda 的 [id=2] 和 Martha 的 [id=3]。

从 EclipseLink 调试输出中,我可以看到 III 向 Sheep 表发出了两个 插入语句。 在数据库中最终有 三个 羊条目,其 ID 如上所列。

此外,我得到以下错误:

[EL Warning]: 2013-06-21 09:53:26.631--UnitOfWork(221387686)--Thread(Thread[main,5,main])--Exception [EclipseLink-7251] (Eclipse Persistence Services - 2.4.1.v20121003-ad44345): org.eclipse.persistence.exceptions.ValidationException
Exception Description: The attribute [id] of class [Sheep] is mapped to a primary key column in the database. Updates are not allowed.

这是 EclipseLink 的错误吗?或者我在这里做错了什么?

最佳答案

您不需要调用 merge(),因为 shepard 已经是一个托管对象。合并适用于分离/序列化的对象,而不是托管对象。如果你在 Sheep 上有一个 cascade persist,那么你不需要做任何事情,只需调用 commit。

但是,调用 merge() 应该不会引起任何问题,所以这很奇怪。如果您可以在测试中重现问题,请记录错误。您可能还想尝试 2.5 版本,看看它是否已修复。

我的猜测是制作 OneToMany EAGER 可能会解决这个问题。此外,如果您为每个事务创建一个新的 EntityManager,那么您就不会遇到这个问题(前提是您在这两种情况下都调用了合并)。

关于java - EclipseLink 以一对多关系生成重复条目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17217080/

相关文章:

java - 当另一个面板动态移动时如何自动正确调整面板大小 java swing

java - 如何为 JPA-Hibernate 定义非 JTA 数据源? org.hibernate.connection.DatasourceConnectionProvider - 找不到数据源 :

java - 刷新后看不到更新记录

jpa - 未设置必需的Derby DataSource属性databaseName

jpa - Hibernate(JPA) key '25-9' 的重复条目 'PRIMARY'

java - Eclipselink实体类自动扫描发现非实体

java - 迭代遍历 n 个嵌套映射和列表

Java间距: Getting error while assigning values

java - Java+Springboot中向远程地址发送http请求并返回响应的几种方式

maven - 如何配置 Helidon 应用程序使用内存数据库进行集成测试?