Ограничение внешнего ключа 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)


Вы не можете использовать чистый 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

Если у вас есть внешний ключ от данных к 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