问题描述
我是JPA的新手,正在做一些实验,希望弄清楚Entity生命周期模型.我希望下面的代码抛出EntityExistsException.但是,它不会抛出预期的异常,而只是在数据库表中创建具有新主键(递增一个)的新行.
I am new to JPA and was experimenting a bit in hope of figuring out the Entity lifecycle model. I expected the code below to throw an EntityExistsException. However, instead of throwing the expected exception, it just creates a new row in database table with a new primary key (incremented by one).
有人可以解释吗?我怀疑这可能与ID字段上的@GeneratedValue注释以及相应表中的自动递增主键有关.
Can anyone explain this? I suspect it might have something to do with the @GeneratedValue annotation on my ID field in combination with my autoincrementing primary key in the corresponding table.
在下面,您可以找到3个代码段:我尝试运行的代码,我的实体定义和我的表设计.
Below you can find 3 snippets: the code I try to run, my entity definition and my table design.
在此先感谢您对我的误会的理解.
I would like to thank you in advance for shining your light on my misunderstanding.
亲切的问候
ps:我将eclipselink用作jpa实现和Derby数据库
ps: I use eclipselink as jpa implementation and a Derby database
脚本:
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;
}
}
推荐答案
仅当持久化与DB关联的相同实体时,才会抛出EntityExistsException.
EntityExistsException will be thrown only when you are persisting the same entity associated with DB.
但是在这里,您创建了一个带有某些值的对象,然后使用针对每个持久性自动生成的唯一主键持久化2次.
but here you have created one Object with some values and then persisting 2 times with primary key generated automatically unique for each persistence.
因为
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
每次您使用实体管理器调用持久方法时,
都会生成新的ID.并且就DB而言,实体变得不同.因为DB关心主键是唯一的,以区分每个记录.
will generate new ID each time you call persist method with Entity manager. and henc eboth the entities becomes different with respect to DB is concerned. because DB cares for primary key to be unque to distinguish each record.
最好这样做以获得该异常
so better you do this to get that exception
首先从数据库中获取实体并进行更改,然后尝试在其上调用保存
get the entity from DB first and change it and try to call save on it
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.让我知道其他任何问题
or else remove autogeneration of primary key and assign it manually same id both the time.let me know for any other questions
这篇关于JPA不会引发EntityExistsException,而是会生成重复的行(自动生成的PK)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!