Hibernate ManyToMany: не вставляет один и тот же идентификатор в обе таблицы - PullRequest
0 голосов
/ 08 октября 2018

У меня (классическая) связь «многие ко многим» с использованием Hibernate и базы данных Oracle.

Я определил свои сущности следующим образом.

Student.java

@Entity
@Table
public class Student implements Serializable {

@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name = "STUDENT_ID")
private Long studentId;

@ManyToMany
@JoinTable(name = "STUDENT_PROJECT", joinColumns = {
        @JoinColumn(name = "STUDENT_ID") }, inverseJoinColumns = {
                @JoinColumn(name = "PROJECT_ID") })
private Set<Project> projects = new HashSet<>();

Project.java

@Entity
@Table
public class Project implements Serializable {

@Id
@Column(name="PROJECT_ID")
private int projectId;

@ManyToMany(mappedBy="projects")
private Set<Student> students = new HashSet<>();

У меня есть таблица STUDENT_PROJECT в моей базе данных Oracle, которая состоит из двух полей, PROJECT_ID и STUDENT_ID с composite primary key на них.

В моей таблице STUDENT есть последовательность для автоматического создания их ID.

TRIGGER STUDENT_TRIGGER
BEFORE INSERT ON STUDENT
FOR EACH ROW

BEGIN
 SELECT STUDENT_SEQUENCE.NEXTVAL
 INTO   :STUDENT_ID
 FROM   dual;
END;

Теперь моя проблема заключается в том, что когда я пытаюсь сохранить свою сущность Student, поле IDтаблица STUDENT не соответствует полю STUDENT_ID таблицы STUDENT_PROJECT.

Каким-то образом она сохраняет идентификатор для ученика и другой идентификатор в таблице сопоставления, и я не могу понять, почему.

Вот как я манипулирую своими объектами

    Student student = new Student();

    // set some fields

    Set<Project> projects = new HashSet<>();

    // call to a private method to set its projects

    student.setProjects(projects);
    studentDao.persist(student);

Мне пришлось удалить foreign key в таблице STUDENT_PROJECT в ID из STUDENT (иначе ограничениене позволил бы мне, конечно, сохранить), чтобы, наконец, заметить, что это устанавливает различные ID, но я не понимаю, почему.

Если вам нужнобольше информации, дайте мне знать, я старался сделать его как можно меньше, спасибо.

ОБНОВЛЕНИЕ:

Я попытался удалить триггер в таблице STUDENT и изменил его конфигурацию Javaна

@Id
@GeneratedValue(strategy = GenerationType.AUTO, generator = "G1")
@SequenceGenerator(name = "G1", sequenceName= "STUDENT_SEQUENCE")
@Column(name = "STUDENT_ID")
private Long studentId;

Теперь я получаю: javax.persistence.EntityExistsException: A different object with the same identifier value was already associated with the session : [fr.persistance.data.Student#3037]

Он вообще не сохраняется в базе данных и выдает указанное выше исключение для persist(), я думаю, у меня проблема смоя последовательность, как кажется, пытается сохранить два Student объекта с одинаковым ID (я зацикливаюсь, чтобы сохранить несколько учеников и их проекты).

Я использовал отладку eclipse для проверки нескольких изМои Student объекты после вызова persist(), и каждый из них имеет разные studentId в Java, но после завершения цикла и транзакции возникает исключение, но кажется, что каждый из них получает отдельный идентификатор.

1 Ответ

0 голосов
/ 08 октября 2018

Проблема заключается в том, что идентификаторы учащихся генерируются базой данных в триггере, а Hibernate пытается создать само значение.

Для базы данных оракула GenerationType.AUTO будет использовать последовательность.Доступ к последовательности осуществляется с помощью Hibernate, который присваивает значение (до того, как ученик фактически будет вставлен в базу данных).

Чтобы Hibernate использовал вашу последовательность, добавьте

@SequenceGenerator(name = "sequence-generator", sequenceName = "STUDENT_SEQUENCE")

и удалите триггер.

Если вы хотите использовать триггер, вам нужно отобразить его как GenerationType.IDENTITY.(Не рекомендуется.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...