我是 JPA 新手,正在进行一些实验,希望找出实体生命周期模型。我预计下面的代码会抛出 EntityExistsException。但是,它并没有抛出预期的异常,而是只是在数据库表中使用新的主键(加一)创建一个新行。
谁能解释一下这个吗?我怀疑这可能与我的 ID 字段上的 @GenerateValue 注释以及相应表中的自动增量主键有关。
下面您可以找到 3 个片段:我尝试运行的代码、我的实体定义和我的表设计。
提前感谢您澄清我的误解。
亲切的问候
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;
}
}
最佳答案
仅当您保留与数据库关联的同一实体时,才会抛出 EntityExistsException。
但在这里,您创建了一个具有某些值的对象,然后持久化了 2 次,并且每次持久化时自动生成唯一的主键。
因为
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
每次使用实体管理器调用 persist 方法时都会生成新的 ID。因此,就 DB 而言,两个实体都变得不同。因为DB关心主键是唯一的来区分每条记录。
所以最好这样做以获得该异常
首先从数据库获取实体并更改它,然后尝试调用保存它
EntityManager em = Persistence.createEntityManagerFactory("jpatest").createEntityManager();
em.getTransaction().begin();
Teacher teacher = em.find(Teacher.class,primary key)
em.persist(teacher);
em.getTransaction().commit();
em.close();
或者删除主键的自动生成并每次都手动为其分配相同的 ID。 如有任何其他问题,请告诉我
关于java - JPA 不抛出 EntityExistsException 但生成重复行(自动生成 PK),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23217972/