Имеет ли cascade = "all-delete-orphan" какое-либо значение в однонаправленной ассоциации "многие ко многим" Hibernate с таблицей соединения?

У меня есть два объекта, которые образуют 9X_.java отношения родитель-потомок, которые имеют 9X_.java отношение «многие ко многим». Следуя рекомендациям 9X_j2se в справочном руководстве по Hibernate, я 9X_java сопоставил это с помощью таблицы соединений:

 ... 

Я 9X_j2se хочу, чтобы один докладчик мог быть связан 9X_.java со многими различными конференциями, но 9X_java-se также чтобы любой докладчик, на который 9X_orphan больше не ссылается какая-либо конференция, был 9X_java-se удален из таблицы speakers (поскольку докладчик 9X_.java без связанных конференций не имеют большое 9X_java значение в моем проекте).

Однако я обнаружил, что 9X_many-to-many если я использую cascade="all-delete-orphan", то если динамик, связанный 9X_cascade с несколькими конференциями, удаляется из 9X_cascade только одной из них, Hibernate пытается удалить сам экземпляр 9X_java-se динамика. .

Ниже приведен модульный тест, демонстрирующий 9X_hibernate такое поведение:

@Test public void testRemoveSharedSpeaker() { int initialCount = countRowsInTable("speakers"); Conference c1 = new Conference("c1"); Conference c2 = new Conference("c2"); Speaker s = new Speaker("John", "Doe"); c1.getSpeakers().add(s); c2.getSpeakers().add(s); conferenceDao.saveOrUpdate(c1); conferenceDao.saveOrUpdate(c2); flushHibernate(); assertEquals(initialCount + 1, countRowsInTable("speakers")); assertEquals(2, countRowsInTable("conference_speakers")); // the remove: c1 = conferenceDao.get(c1.getId()); c1.getSpeakers().remove(s); flushHibernate(); assertEquals("count should stay the same", initialCount + 1, countRowsInTable("speakers")); assertEquals(1, countRowsInTable("conference_speakers")); c1 = conferenceDao.get(c1.getId()); c2 = conferenceDao.get(c2.getId()); assertEquals(0, c1.getSpeakers().size()); assertEquals(1, c2.getSpeakers().size()); } 

При обработке удаления s из 9X_java-api c1.speakers возникает ошибка, поскольку Hibernate удаляет 9X_jdk как строку в таблице соединения, так и строку 9X_java-libraries таблицы speakers:

DEBUG org.hibernate.SQL - удалить 9X_jre из конференции_speakers, где Conference_id 9X_openjdk =? и Speaker_id =?
DEBUG org.hibernate.SQL 9X_jdk - удалить из динамиков, где id =?

Если я 9X_cascade изменю cascade="all-delete-orphan" только на cascade="all", тогда этот тест будет 9X_java-libraries работать, как ожидалось, хотя он приведет 9X_orphan к нежелательному поведению, при котором 9X_java-api в моей таблице speakers останутся потерянные строки.

Это 9X_orphan заставляет меня задаться вопросом - может 9X_oraclejdk ли Hibernate вообще знать, когда удалять 9X_cascade осиротевшие объекты из дочерней стороны 9X_cascade отношения, но только тогда, когда на ребенка 9X_cascade не ссылаются другие родители (независимо 9X_orphan от того, являются ли эти родители в текущем 9X_core-java Session)? Возможно, я неправильно использую cascade="all-delete-orphan"?

Я 9X_java-libraries получаю такое же точное поведение, если 9X_java использую аннотации JPA вместо сопоставления 9X_core-java XML, например:

@ManyToMany(cascade = CascadeType.ALL) @JoinTable(name = "conference_speakers", joinColumns = @JoinColumn(name = "conference_id"), inverseJoinColumns = @JoinColumn(name = "speaker_id")) @org.hibernate.annotations.Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN) private Set speakers = new HashSet(); 

Это, кстати, Hibernate 3.6.7.Final.

11
0
1
Общее количество ответов: 1

Ответ #1

Ответ на вопрос: Имеет ли cascade = "all-delete-orphan" какое-либо значение в однонаправленной ассоциации "многие ко многим" Hibernate с таблицей соединения?

Каскадный режим DELETE_ORPHAN не определен 9X_jdk для связи "многие ко многим" - только 9X_openjdk для связи "один ко многим" (последний 9X_.java имеет атрибут orphanRemoval = true | false 9X_java-se в стандартной аннотации JPA @OneToMany, поэтому вы 9X_javax не приходится прибегать к проприетарной 9X_oraclejdk аннотации Hibernate).

Причина этого в точности 9X_jdk такая, как вы описали - Hibernate не может 9X_cascade определить, действительно ли "осиротевший" конец 9X_jdk отношения "многие ко многим" без 9X_javax выполнения запроса к базе данных, который 9X_openjdk одновременно является счетчиком -интуитивно 9X_jdk понятен и может (потенциально) иметь серьезные 9X_many-to-many последствия для производительности.

Таким 9X_jdk образом, описанное вами поведение гибернации 9X_java-se является правильным (ну, «как задокументировано»); хотя 9X_openjdk в идеальном мире это бы предупредило вас 9X_java-api о том, что DELETE_ORPHAN недопустим для "многие-ко-многим" во 9X_hibernate время компиляции сопоставлений 2-го прохода.

Честно 9X_java-libraries говоря, я не могу придумать хороший способ 9X_.java достичь того, чего вы хотите. Самым простым 9X_jre (но зависящим от базы данных) способом, вероятно, было 9X_jdk бы определение триггера при удалении из 9X_hibernate conference_speakers, который проверял бы, действительно ли 9X_orphan этот динамик осиротел, и удалял бы его из 9X_java speakers, если это так. Независимый от базы данных 9X_java-libraries вариант - сделать то же самое вручную в 9X_jre DAO или прослушивателе.

Обновление: Вот отрывок из Hibernate docs (глава 9X_oraclejdk 11.11, сразу после серого примечания на 9X_jre CascadeType.ALL), основные моменты принадлежат 9X_orphan мне:

Специальный каскадный стиль delete-orphan применяется только к "один ко многим". ассоциаций и указывает, что 9X_many-to-many операция delete() должна быть применяется 9X_jdk к любому дочернему объекту, удаленному из 9X_jre ассоциации.

Далее вниз:

Обычно не имеет смысла 9X_java-libraries включать каскад для много-к-одному или ассоциация 9X_orphan "многие ко многим". На самом деле 9X_java @ManyToOne и @ManyToMany не даже предложите 9X_orphan атрибут orphanRemoval. Каскадирование часто 9X_jdk полезно для ассоциации "один к одному" и 9X_core-java "один ко многим".

16
0