#java #spring-boot #many-to-many #one-to-many #composite-key
Вопрос:
У меня есть две сущности (Курс и Пользователь), связанные @ManyToMany
. User
может оценивать множество курсов и Course
может быть оценен несколькими пользователями. Поэтому я должен хранить в своей базе userId
данных courseId
и рейтинг , соответствующий этой ассоциации. Следуя этому примеру, я сделал такие сущности:
public class Course {
@Id
@GeneratedValue(generator = "inc")
@GenericGenerator(name = "inc", strategy = "increment")
private int courseId;
@NotBlank(message = "Add the course's title!")
private String title;
@OneToMany(mappedBy = "course", cascade = CascadeType.ALL)
private Set<CourseRating> ratings;
}
public class User {
@Id
@GeneratedValue(generator = "inc")
@GenericGenerator(name = "inc", strategy = "increment")
private int userId;
@NotBlank(message = "Add username!")
private String name;
@OneToMany(mappedBy = "user")
private Set<CourseRating> ratings;
}
И моя ассоциативная сущность с составным ключом:
public class CourseRating {
@EmbeddedId
private CourseRatingKey id;
@ManyToOne
@MapsId("userId")
@JoinColumn(name = "user_id")
private User user;
@ManyToOne
@MapsId("courseId")
@JoinColumn(name = "course_id")
private Course course;
private Double rating = null;
public CourseRating() {
}
public CourseRating(CourseRatingKey key) {
this.id = key;
}
Где составной ключ выглядит следующим образом:
public class CourseRatingKey implements Serializable {
@Column(name = "user_id")
private int userId;
@Column(name = "course_id")
private int courseId;
// equals() amp; hashCode()
}
Моя логика, ответственная за привязку пользователя к курсу (сейчас даже не оценена):
@Transactional
public CourseRating buyCourse(CourseRatingKey key) {
var relationship = new CourseRating(key);
var user = userRepository.findById(key.getUserId())
.orElseThrow(() -> new IllegalArgumentException("No user with given id"));
var course = repository.findById(key.getCourseId())
.orElseThrow(() -> new IllegalArgumentException("No course with given id"));
course.setRatings(new HashSet<>(Set.of(relationship)));
user.setRatings(new HashSet<>(Set.of(relationship)));
relationship.setCourse(course);
relationship.setUser(user);
// ratingRepository is `CourseRatingRepository` that extends
// JpaReposiory<CourseRating, CourseRatingKey>
return ratingRepository.save(relationship);
}
объяснение логики: @ManyToMany
на самом деле это похоже на двойную @OneToMany
( двунаправленную в моем случае ) аннотацию, поэтому я должен синхронизировать обе стороны этих ассоциаций.
когда эта логика выполняется, я получаю такую ошибку:
javax.persistence.EntityExistsException: A different object with the same identifier value was already associated with the session : [com.projects.spring.udemy.relationship.CourseRating#com.projects.spring.udemy.relationship.CourseRatingKey@239a]