【发布时间】:2014-04-22 11:20:07
【问题描述】:
我是 JPA 的新手,正在做一些实验,希望能弄清楚实体生命周期模型。我预计下面的代码会抛出 EntityExistsException。然而,它并没有抛出预期的异常,而是在数据库表中创建了一个新行,带有一个新的主键(加一)。
谁能解释一下?我怀疑这可能与我的 ID 字段上的 @GeneratedValue 注释以及相应表中的自动递增主键有关。
您可以在下面找到 3 个 sn-ps:我尝试运行的代码、我的实体定义和我的表格设计。
我要提前感谢您为我的误解开光。
亲切的问候
ps:我使用 eclipselink 作为 jpa 实现和一个 Derby 数据库
脚本:
Teacher teacher = new Teacher("John","Doe","English");
//Persist John Doe
EntityManager em = Persistence.createEntityManagerFactory("jpatest").createEntityManager();
em.getTransaction().begin();
em.persist(teacher);
em.getTransaction().commit();
em.close();
//Try to persist John Doe a second time
em = Persistence.createEntityManagerFactory("jpatest").createEntityManager();
em.getTransaction().begin();
em.persist(teacher);
em.getTransaction().commit(); //I Expect a throw here
em.close();
表格设计:
CREATE TABLE teachers (id INT GENERATED ALWAYS AS IDENTITY, firstname VARCHAR(20) ,lastname VARCHAR(40), PRIMARY KEY(id))
实体定义:
package testpackage;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Transient;
@Entity
@Table(name="teachers", schema="USERNAME")
public class Teacher {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String firstName;
private String lastName;
@Transient
private String course;
/**
* Zero argument constructor for JPA
*/
Teacher(){
}
public Teacher(String firstName, String lastName, String course){
this.firstName = firstName;
this.lastName = lastName;
this.course = course;
}
public int getId(){
return id;
}
public String getFirstName(){
return firstName;
}
public String getLastname(){
return lastName;
}
public String getCourse(){
return course;
}
public void setFirstName(String firstName){
this.firstName = firstName;
}
public void setLastName(String lastName){
this.lastName = lastName;
}
}
【问题讨论】:
-
对我来说这看起来像是一个 eclipselink 错误。 EclipseLink 应该将实体视为分离的实体,并且规范说如果将分离的实体传递给 persist(),则必须抛出异常。
-
问题将是教师实例在第一次提交后没有分配 id。如果没有 id,第二次持久调用应该会成功,因为它没有身份,因此必须是新的。打开对所有或最好的日志记录,看看日志中是否有任何问题的迹象,例如使用了错误的数据库平台,或者 EclipseLink 没有正确发出插入。数据库中为 id 使用了哪些值?如果您切换到使用 Integer 而不是 int 或不同的生成策略,它是否有效?
标签: java jpa eclipselink derby