Ограничение внешнего ключа JPA 2.0

У меня простое отношение OneToOne:
Данные ‹-> TherapyResult

Я хотел бы выразить следующие ограничения с помощью JPA.

  1. Если объект Data удаляется, связанный с ним TherapyResult также должен быть удален.
  2. Если объект TherapyResult удаляется, связанный с ним объект Data должен оставаться в базе данных.

Первое ограничение очень просто с JPA, так как я могу добавить CascadingType.REMOVE

@OneToOne(cascade = { CascadeType.REMOVE, CascadeType.REFRESH })
private TherapyResult therapyResult;

Для второго ограничения я хотел бы добавить что-то вроде

@JoinColumn(columnDefinition = "DATA_ID BIGINT CONSTRAINT THERAPYRESULTDTAID FOREIGN KEY (DATA_ID) REFERENCES DATA (ID) ON DELETE SET NULL")

Однако это не работает. В OpenJPA похоже есть что-то похожее, но я хочу использовать JPA 2.0 и EclipseLink. Внешний ключ OpenJPA.

Другим решением может быть использование @PreRemove описано здесь , который работает, но выглядит для меня немного "не передовой практикой". Однако только ощущение.

Моя установка: Eclipse 3.7.1 EclipseLink 2.3 Apache Derby 10.8.3 и/или HSQLDB

любая помощь приветствуется, Муки


person Muki    schedule 13.03.2012    source источник


Ответы (2)


arrow_upward
2
arrow_downward

Вы не можете использовать чистый JPA для указания внешних ключей... эта спецификация не включает эту возможность. JDO — единственный стандарт с возможностью определения FK. Вы должны использовать особенности реализации или просто определить схему самостоятельно и позволить реализации JPA работать на ней.

person DataNucleus    schedule 13.03.2012
comment
Это кажется недействительным с JPA 2.1: docs.jboss.org/hibernate/jpa/2.1/api/javax/persistence/ - person Piohen; 08.10.2014

arrow_upward
2
arrow_downward

Если у вас есть внешний ключ от данных к TherapyResult, и данные являются владельцем ассоциации, то

  • удаление данных приведет к автоматическому удалению TherapyResult, если для каскада установлено значение REMOVE.
  • вам просто нужно установить для поля therapyResult значение null, а затем удалить TherapyResult, чтобы получить то, что вам нужно. Другой вариант — установить для orphanRemoval значение true, и в этом случае достаточно установить для поля therapyResult значение null, чтобы удалить его из базы данных.

Если у вас есть внешний ключ от TherapyResult к Data, а TherapyResult является владельцем ассоциации, то

  • удаление данных приведет к автоматическому удалению TherapyResult, если каскад установлен на REMOVE в поле Data.therapyResult.
  • удаление TherapyResult оставит данные в базе данных при условии, что каскад не установлен на REMOVE в поле TherapyResult.data
person JB Nizet    schedule 13.03.2012
comment
Хорошо, но что произойдет, если отношения будут «Многие TherapyResult к одним данным», а внешний ключ — от TherapyResult к данным? Как это возможно: удаление TherapyResult не удаляет Данные; удаление данных удаляет все связанные результаты TherapyResults? - person Rui Marques; 23.09.2013
comment
Отмена терапии только сделает это. Удаление данных приведет к удалению результатов терапии, если связь между данными и результатом терапии имеет каскад REMOVE. Вот что означает каскад для ассоциации: когда вы выполняете X для сущности, также выполняйте X для связанных сущностей. - person JB Nizet; 23.09.2013