java - JPA 持久保存与现有实体有关系的新实体

标签 java jpa eclipselink

我有两个具有 @ManyToMany 关系的实体,让我们以学生和类(class)为例,如果列表中有新学生,我将保留一个包含学生列表的新类(class)它应该级联新的,如果存在它应该更新它。

对于新学生和新类(class),它工作得很好,但对于新类(class)和现有学生,我会从数据库中抛出一个唯一的约束违规。关系类似于下面。

@Entity
@Table
public class Course implements Serializable {

    @Id
    @Column(name = "CRS_ID")
    @SequenceGenerator(name = "rcrsSeq", sequenceName = "CRS_SEQ", allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "rcrsSeq")
    private Long id;

    @ManyToMany(cascade = {
        CascadeType.PERSIST,
        CascadeType.MERGE,
        CascadeType.REFRESH,
        CascadeType.DETACH
    })
    @JoinTable(name = "student_courses",
        uniqueConstraints = @UniqueConstraint(columnNames = {"STU_ID", "CRS_ID"}),
        joinColumns = {@JoinColumn(name = "CRS_ID")},
        inverseJoinColumns = {@JoinColumn(name = "STU_ID")}
    )
    private List<Student> students;

    //getters and setters

}


@Entity
@Table(uniqueConstaints = @UniqueConstraint(columnNames = {"username"}))
public class Student implements Serializable {

    @Id
    @Column(name = "STU_ID")
    @SequenceGenerator(name = "rstuSeq", sequenceName = "STU_SEQ", allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "rstuSeq")
    private Long id;

    @ManyToMany(mappedBy = "students")
    private List<Course> courses;


    private String userName;

    //getters and setters

    // equals + hashcode based on userName

}

在坚持之前,我尝试使用实体管理器查找学生,如果该学生存在,则使用该实例而不是新的学生实例。这也不起作用,它仍然尝试执行插入而不是更新

最佳答案

你写了

in the case of a new course and an existing student however I get a unique constraint violation being thrown from the database.

如果您想保留新的 Course 对象和现有的 Student 对象,您应该执行以下操作:

  1. 创建类(class)的实例:

    Course course = new Course(...);
    
  2. 获取现有学生:

    Student student = entityManager.find(Student.class, id_of_student);
    
  3. 按如下方式连接关系:

    course.getStudents.add(student);
    student.getCourse().add(course);
    
  4. 实际上,您应该调用 entityManager.persist() 来保存新实体。但在这种情况下,这将不起作用,因为 student 不是新的实体实例,并且 persist() 不会保存现有的实体实例。因此,您可以使用 entityManager.merge(),即使它在语义上不正确(因为 merge 应该用于分离的实体):

    entityManager.merge(course);
    

为了使其工作,您应该调用事务中的所有实体管理器方法。

关于java - JPA 持久保存与现有实体有关系的新实体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47139907/

相关文章:

java - 在网页上的表格中显示值

java - 每个窗口只打开一次

java - JPA 新手 - 每次保存包含实体时不要保存现有成员

java - Glassfish JPA : Problems injecting EntityManager

sql - 在什么情况下 SELECT by PRIMARY KEY 会很慢?

java - Spring webclient,有多少个实例?

java - 如何在 Google 电子表格中获取单个工作表的工作表名称 - Google Sheet Api v4 - Java

java - 如何获取查询中实体的嵌套列表的总大小?

mysql - 如何使用EclipseLink和Joda-Time将UTC中的日期时间存储到数据库中?

java - 是否可以在 jpa 中调用不调用 setter 的情况下更新实体