JPA не может удалить @OneToOne, если определено @JoinTable - PullRequest
0 голосов
/ 10 января 2019

У меня есть забавная «проблема», то есть явление.

Краткая информация:

  • _BaseEntity - это @MappedSuperclass, который обрабатывает ID, hashCode, equals, CompareTo и т. Д. И отлично работает во всех моих проектах)
  • Я использую Payara (EclipseLink) на БД MySQL
  • @Expose - это тег GSON
  • Я нашел много похожих тем, но ни один из них не ответил на мой вопрос, не сделал различий с / без @JoinTable, или не получил ответ в виде решения ...
  • отношение является односторонним, то есть только с Thema->TopThema, и явно НЕТ TopThema->Thema

ПРИМЕР РАБОТЫ Когда у меня есть сущность, настроенная так:

@Entity
@Table(name = Thema.TABLE_NAME)
public class Thema extends _BaseEntity {
    static public final String TABLE_NAME = UEntity.TABLE_PREFIX + "Thema";

    @Expose @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true) 
    private TopThema topThema;
}

Я могу просто EntityManager.remove () it.

.

ПРИМЕР НЕ РАБОТАЕТ :

Но , если это определено так

@Entity
@Table(name = Thema.TABLE_NAME)
public class Thema extends _BaseEntity {
    static public final String TABLE_NAME = UEntity.TABLE_PREFIX + "Thema";

    @Expose @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true) 
    @JoinTable(name = TABLE_NAME + "_topThema")
    private TopThema topThema;
}

(с промежуточной таблицей "GP_Thema_topThema", как определено @JoinTable(name = TABLE_NAME + "_topThema") затем EntityManager.remove () выдает исключение:

com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Невозможно удалить или обновить родительскую строку: ограничение внешнего ключа не выполнено (test_PT_local. GP_Thema_topThema, ОГРАНИЧЕНИЕ FK_GP_Thema_topThema_topThema_ID ИНОСТРАННЫЙ КЛЮЧ (topThema_ID) ССЫЛКИ GP_TopThema (ID))

Я знаю, что не имеет особого смысла использовать дополнительные @JoinTable, когда ссылка также может быть просто сохранена внутри "GP_Thema" как "GP_Thema". 'TOPTHEMA_ID'. Плюс: оба определения сущностей одинаково хорошо работают на стороне Java.

Но из интереса: почему JPA не может удалить запись в @JoinTable GP_Thema_topThema, хотя я установил cascade = CascadeType.ALL и orphanRemoval = true?

Обновление: А из-за @JoinTable я тоже не могу - сначала удалите TopThema, затем Thema (выбрасывает MySQLIntegrityConstraintViolationException при удалении TopThema) - det Thema.topThema = null, затем обновить (снова выбрасывает MySQLIntegrityConstraintViolationException)

Ответы [ 2 ]

0 голосов
/ 25 января 2019

Как примечание, вы можете удалить вашу Thema сущность, используя JPA и MySQL ... Для этого вам просто нужно объявить внешние ключи вашей @JoinTable (GP_Thema_topThema) как "ON DELETE CASCADE" .. .

Пример:

CREATE TABLE GP_Thema_topThema(
    thema_ID integer NOT NULL,
    topThema_ID integer NOT NULL,
    FOREIGN KEY (thema_ID)
        REFERENCES thema (id)
        ON DELETE CASCADE,
    FOREIGN KEY (topThema_ID)
        REFERENCES top_thema(id)
        ON DELETE CASCADE
)

Таким образом, если база данных получит команду на удаление сущности Thema, все связанные с ней сущности GP_Thema_topThema (или кортежи) также будут удалены ...

0 голосов
/ 24 января 2019

Не JPA не может удалить объект, но фактическую базу данных. То, что вы ищете, - это отложенное ограничение, а в MySQL это невозможно.

Mysql docs относительно ограничений, которые можно отложить здесь

Как и MySQL в целом, в операторе SQL, который вставляет, удаляет или обновляет много строк, InnoDB проверяет ограничения UNIQUE и FOREIGN KEY строка за строкой. При выполнении проверок внешнего ключа InnoDB устанавливает общие блокировки на уровне строк для дочерних или родительских записей, которые он должен просматривать. InnoDB немедленно проверяет ограничения внешнего ключа; проверка не откладывается до фиксации транзакции. Согласно стандарту SQL, поведение по умолчанию должно быть отложено. То есть ограничения проверяются только после обработки всего оператора SQL. Пока InnoDB не реализует отложенную проверку ограничений, некоторые вещи невозможны, такие как удаление записи, которая ссылается на себя с использованием внешнего ключа

Рассматривали ли вы переход на PostgreSQL ?

Отложенные ограничения не проверяются до фиксации транзакции

...