我正在使用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进行命名查询,我得到了“Tilda”的重复条目!
当我编码
时,不会发生这种情况em.persist(martha);
作为最后一个实体管理员访问,而不是。
分析调试输出,我可以看到在 II 之后,有一个[id = 1]的Shepard对象和一个[id = 1]的Sheep对象。 在 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的错误吗?或者我做错了什么,这里?
答案 0 :(得分:2)
在Sheep类中,你有一个Shepherd类的“外键”,它不是主键的一部分。
尝试创建Id类以在Sheep类中使用复合键。
@Id
@ManyToOne(fetch = FetchType.EAGER, optional = false)
@JoinColumn(name="shepard_id")
private Shepard shepard;
答案 1 :(得分:2)
您不需要调用merge(),因为shepard已经是托管对象。合并用于分离/序列化对象,而不是托管对象。如果你有一个cascade持续存在于Sheep,那么你不需要做任何事情,只需调用commit。
但是,调用merge()不应该导致任何问题,所以这很奇怪。如果您可以在测试中重新创建问题,请记录错误。您可能还想尝试2.5版本,看它是否已修复。
我的猜测是,制作OneToMany EAGER可能会解决问题。此外,如果您为每个事务创建一个新的EntityManager,那么您就不会遇到问题(前提是您在两种情况下都调用了merge)。