我正在使用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();

然后对绵羊进行命名查询,我得到一个重复的“蒂尔达”条目!

当我编码时不会发生这种情况
em.persist(martha);

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

分析调试输出,可以看到 II 之后,有一个Shepard对象的[id = 1]和一个Sheep对象的[id = 1]。
III 之前和之后,Shepard拥有两个羊的引用,之前是Tilda的[id = 1 ]和Martha的[id = null]。
III 之后,Shepard持有两个绵羊的引用,其中Tilda为[id = 2 ],Martha为[id = 3]。

从EclipseLink调试输出中,我可以看到 III 向Sheep表中发出了两个插入语句。
在数据库中,最后出现三个 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上有一个级联持久性,那么您无需执行任何操作,只需调用commit。

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

我的猜测是制作OneToMany EAGER可能会解决此问题。同样,如果为每个事务创建一个新的EntityManager,那么就不会有问题(假设在两种情况下都调用merge)。

08-06 20:01