java - JPA 不抛出 EntityExistsException 但生成重复行(自动生成 PK)

标签 java jpa eclipselink derby

我是 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/

相关文章:

hibernate - 使用 JPA/Hibernate 进行继承映射

java - 在 Spring Data JPA 中连接两个表并从存储库查询两个表数据

java - 在 EclipseLink 上使用投影时出现 NotReadablePropertyException

java - 使用 java 使用 selenium webdriver 从 Gmail 收件箱打开邮件

java - 在类文件中添加总计

java - 调用持久/合并时如何忽略级联

java - Spring JPA、Eclipselink 和审计

java - JPA 鉴别器值

Java SE 8 : Minimal JSON webservice

java - 使用第一个元素和附加集合进行列表初始化