JPA @ManyToOne с CascadeType.ALL
Я думаю, что я пропустил понимание значения каскадирования в контексте отношений @ManyToOne
.
Случай:
public class User { @OneToMany(fetch = FetchType.EAGER) protected Set userAddresses; } public class Address { @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) protected User addressOwner; }
В чем смысл cascade = CascadeType.ALL
? Например, если я удалю определенный адрес из базы данных, как тот факт, что я добавил cascade = CascadeType.ALL
влияет на мои данные (пользователь, я думаю)?
- Совместное использование сущностей между модулями App Engine
- Единые DAO и общие методы CRUD (JPA / Hibernate + Spring)
- Spring Boot, Spring Data JPA с несколькими источниками данных
- Spring-Data-Jpa Repository - Подчеркивание имени столбца объекта
- JPA: как иметь отношение «один ко многим» одного и того же типа Entity
- Сделать hibernate игнорировать переменные classа, которые не отображаются
- IllegalStateException с Hibernate 4 и ManyToOne каскадом
- JPA "@JoinTable" аннотация
- Как хранить дату и время и временные метки в часовом поясе UTC с JPA и Hibernate
- Объединение двух элементов таблицы в Spring Data JPA
- Перечисление карты в JPA с фиксированными значениями?
- Установка значений по умолчанию для столбцов в JPA
- Можно ли динамически определять имена столбцов в Hibernate / JPA?
Значение CascadeType.ALL
состоит в том, что настойчивость будет распространять (каскадировать) все операции EntityManager
( PERSIST, REMOVE, REFRESH, MERGE, DETACH
) для связанных объектов.
Кажется, в вашем случае это плохая идея, так как удаление Address
приведет к удалению связанного User
. Поскольку пользователь может иметь несколько адресов, другие адреса станут сиротами. Однако обратный случай (аннотация User
) имеет смысл – если адрес принадлежит только одному пользователю, безопасно распространять удаление всех адресов, принадлежащих пользователю, если этот пользователь удален.
BTW: вы можете добавить mappedBy="addressOwner"
к своему User
чтобы сообщить поставщику персистентности, что столбец соединения должен находиться в таблице ADDRESS.
См. Здесь пример из документов OpenJPA. CascadeType.ALL
означает, что он выполнит все действия.
Цитата:
CascadeType.PERSIST: при сохранении сущности также сохраняются сущности, хранящиеся в этом поле. Мы предлагаем либеральное применение этого каскадного правила, потому что если EntityManager находит поле, которое ссылается на новый объект во время флеша, и поле не использует CascadeType.PERSIST, это ошибка.
CascadeType.REMOVE: при удалении объекта также удаляются сущности, хранящиеся в этом поле.
CascadeType.REFRESH: при обновлении объекта также обновляйте объекты, содержащиеся в этом поле.
CascadeType.MERGE: при объединении состояния объекта также объединяются сущности, хранящиеся в этом поле.
Себастьян
Из спецификации EJB3.0 :
Использование элемента каскадной annotations может использоваться для распространения эффекта операции на связанные объекты. Каскадная функциональность наиболее часто используется в отношениях родитель-потомок.
Если X – управляемый объект, операция удаления приводит к его удалению. Операция удаления каскадируется для объектов, на которые ссылается X, если отношения из X с этими другими объектами аннотируются с помощью значения элемента cascade = REMOVE или cascade = ALL.
Итак, в двух словах, отношения сущностей, определенные с помощью CascadeType.All
, гарантируют, что все CascadeType.All
события, такие как сохранение, обновление, слияние и удаление, которые происходят у родителя, будут переданы дочернему элементу. Определение других опций CascadeType
предоставляет разработчику более узкий уровень контроля над тем, как ассоциация сущностей обрабатывает постоянство.
Например, если у меня была объектная книга, содержавшая список страниц, и я добавляю объект страницы в этот список. Если аннотация @OneToMany
определяющая связь между книгой и страницей, отмечена как CascadeType.All
, сохранение Книги приведет к тому, что страница также будет сохранена в базе данных.
Как я объяснил в этой статье, и в моей книге « Высокоуровневая стойкость Java» вы никогда не должны использовать CascadeType.ALL
в @ManyToOne
поскольку переходы состояний сущностей должны распространяться с родительских объектов на @ManyToOne
.
@ManyToOne
всегда является @ManyToOne
ассоциацией, так как она должна отображать базовый FK.
Поэтому переместите CascadeType.ALL
из ассоциации @ManyToOne
в @OneToMany
которая должна использовать атрибут mappedBy
поскольку это наиболее эффективное сопоставление «один ко многим» . `
В JPA 2.0, если вы хотите удалить адрес, если вы удалили его из пользовательского объекта, вы можете добавить orphanRemoval=true
(вместо CascadeType.REMOVE
) к вашему @OneToMany
.
Больше объяснений между orphanRemoval=true
и CascadeType.REMOVE
здесь .