【问题标题】:JPA persist new entity with relationship to existing entityJPA 持久化与现有实体有关系的新实体
【发布时间】:2017-11-06 15:05:47
【问题描述】:

我有两个具有@ManyToMany 关系的实体,让我们举一个常见的例子 Student 和 Course,我正在保存一个包含学生列表的新课程,如果列表中有新学生,它应该级联新的,如果它存在,它应该更新它。

对于新学生和新课程,它可以正常工作,但对于新课程和现有学生,我会从数据库中抛出一个独特的约束违规。关系类似于下面。

@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

}

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

【问题讨论】:

  • 也许你需要添加确切的代码来重现这个。还有唯一的约束违反异常详细信息。最后但并非最不重要的一点是,如果碰巧有唯一字段提及这些字段,例如,许多学生可以有相同的用户名吗?

标签: java jpa eclipselink


【解决方案1】:

你写的

在新课程和现有学生的情况下,但是我从数据库中抛出了唯一的约束违规。

如果您想持久化一个新的Course 对象和一个现有的Student 对象,您应该执行以下操作:

  1. 创建Course的实例:

    Course course = new Course(...);
    
  2. 获取现有的Student

    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);
    

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

【讨论】:

    猜你喜欢
    • 2016-06-10
    • 1970-01-01
    • 2012-12-17
    • 2018-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多