2

I have two entities with a @ManyToMany relationship, let's take a common example Student and Course, I'm persisting a new course with a list of students, if a new student is in the list it should cascade the new one, if it's existing it should update it.

For the case of a new student and new course it works fine, in the case of a new course and an existing student however I get a unique constraint violation being thrown from the database. Relationship is similar to the below.

@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

}

Before persisting I have tried doing a find of a student using the entitymanager and if that student exists use that instance instead of the new student instance. This also doesn't work and it still tries to do an insert instead of an update

PDStat
  • 5,513
  • 10
  • 51
  • 86
  • Maybe you need to add exact code how you can reproduce this. Also the unique constraint violation exception details. And the last but not the least if there happens to be uniquie fields mention those also, for example, can many students have the same userName? – pirho Nov 06 '17 at 16:04

1 Answers1

4

You wrote

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

If you want to persist a new Course object and an existing Student object you should do the following:

  1. Create an instance of Course:

    Course course = new Course(...);
    
  2. Fetch an existing Student:

    Student student = entityManager.find(Student.class, id_of_student);
    
  3. Wire the relationships as follows:

    course.getStudents.add(student);
    student.getCourse().add(course);
    
  4. Actually you should call entityManager.persist() to save a new entity. But in this case that will not work because the student is not new entity instance, and persist() will not save an existing entity instance. So you can use entityManager.merge() even though it is not semantically correct (because merge is supposed to be used on detached entities) :

    entityManager.merge(course);
    

In order for this to work, you should call all the entity manager methods in a transaction.

ujulu
  • 3,289
  • 2
  • 11
  • 14