JPA 2.0 orphanRemoval=true против delete Cascade
Я немного смущен JPA 2.0 .
Я думаю, что вижу, что это необходимо, когда я использую инструменты генерации БД моего провайдера JPA для создания базовой базы данных DDL, чтобы иметь ON DELETE CASCADE
об определенном отношении.
однако, если БД существует и у него уже есть ON DELETE CASCADE
в отношении отношения этого недостаточно, чтобы каскадировать удаление соответствующим образом? Что делает orphanRemoval
сделать дополнительно?
Ура
7 ответов
orphanRemoval
не имеет ничего общего с ON DELETE CASCADE
.
orphanRemoval
полностью ORM-специфическая вещь. Он помечает "дочернюю" сущность, которая должна быть удалена, когда на нее больше не ссылаются из "родительской" сущности, например, когда вы удаляете дочернюю сущность из соответствующей коллекции родительской сущности.
ON DELETE CASCADE
это
пример взят из формы здесь:
когда Employee
объект сущности удаляется, операция удаления каскадируется в ссылочный Address
объект. В связи с этим, orphanRemoval=true
и cascade=CascadeType.REMOVE
идентичны, и если orphanRemoval=true
указано, CascadeType.REMOVE
избыточна.
разница между двумя настройками заключается в ответе на отключение отношения. Например, например, при установке поля адреса в null
или еще Address
объект.
если
orphanRemoval=true
указано отключенномAddress
экземпляр автоматически удаляется. Это полезно для очистки зависимых объекты (например,Address
) , который не должен существовать без ссылки из объект владельца (например,Employee
).если только
cascade=CascadeType.REMOVE
указано, нет автоматического действия взято с отключением отношения не удалить операция.
чтобы не болтались ссылки в результате удаления сироты эта функция должна быть включена только для полей, содержащих частные не общие зависимые объекты.
надеюсь, это прояснит ситуацию.
в момент удаления дочернего объекта из коллекции вы также будете удалять этот дочерний объект из БД. orphanRemoval также подразумевает, что вы не можете изменить родителей; если есть отдел, в котором есть сотрудники, как только вы удалите этого сотрудника, чтобы поместить его в другой отдел, вы случайно удалите этого сотрудника из БД при flush/commit(whichver приходит первым). Мораль-установить orphanRemoval в true до тех пор, пока вы уверены, что дети этого родителя не будет мигрировать к другому родителю на протяжении всего их существования. Включение orphanRemoval также автоматически добавляет REMOVE в список каскадов.
эквивалентное сопоставление JPA для DDL ON DELETE CASCADE
is cascade=CascadeType.REMOVE
. Бесхозное удаление означает, что зависимые сущности удаляются при уничтожении связи с их "родительской" сущностью. Например, если ребенок удаляется из @OneToMany
отношение без явного удаления его в диспетчере сущностей.
@GaryK ответ абсолютно отличный, я потратил час на поиски объяснения orphanRemoval = true
vs CascadeType.REMOVE
и это помогло мне понять.
подводим итоги: orphanRemoval = true
работает идентично как CascadeType.REMOVE
ТОЛЬКО ЕСЛИ мы удаляем объект (entityManager.delete(object)
) и мы хотим, чтобы объекты childs также были удалены.
в совершенно разных sitiuation, когда мы извлекаем некоторые данные, такие как List<Child> childs = object.getChilds()
а затем удалить ребенка (entityManager.remove(childs.get(0)
) через orphanRemoval=true
приведет к тому, что лицо соответствует childs.get(0)
будет удален из базы данных.
удаление сироты имеет тот же эффект, что и при удалении каскада в следующем сценарии:- Допустим, у нас есть простое отношение "много к одному" между сущностью student и сущностью guide, где многие студенты могут быть сопоставлены с тем же руководством, и в базе данных у нас есть отношение внешнего ключа между Student и таблицей Guide, такое что таблица student имеет id_guide как FK.
@Entity
@Table(name = "student", catalog = "helloworld")
public class Student implements java.io.Serializable {
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "id")
private Integer id;
@ManyToOne(cascade={CascadeType.PERSIST,CascadeType.REMOVE})
@JoinColumn(name = "id_guide")
private Guide guide;
// родительская сущность
@Entity
@Table(name = "guide", catalog = "helloworld")
public class Guide implements java.io.Serializable {
/**
*
*/
private static final long serialVersionUID = 9017118664546491038L;
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "id", unique = true, nullable = false)
private Integer id;
@Column(name = "name", length = 45)
private String name;
@Column(name = "salary", length = 45)
private String salary;
@OneToMany(mappedBy = "guide", orphanRemoval=true)
private Set<Student> students = new HashSet<Student>(0);
в этом сценарии отношения таковы, что студент сущность является владельцем отношения, и поэтому нам нужно сохранить сущность student, чтобы сохранить весь граф объектов, например
Guide guide = new Guide("John", "00");
Student s1 = new Student(guide, "Roy","ECE");
Student s2 = new Student(guide, "Nick", "ECE");
em.persist(s1);
em.persist(s2);
здесь мы сопоставляем одно и то же руководство с двумя различными объектами student и начиная с каскада.Используется PERSIST, граф объектов будет сохранен, как показано ниже в таблице базы данных (MySql в моем случае)
таблица студентов: -
ID Name Dept Id_Guide
1 Рой ЕСЕ 1
2 Ник ECE 1
таблица:-
ID имя зарплата
1 Джон $ 1500
и теперь, если я хочу удалить один из студентов, используя
Student student1 = em.find(Student.class,1);
em.remove(student1);
и когда запись студента удаляется, соответствующая запись руководства также должна быть удалена, вот где каскад.Удалить атрибут в сущности Student входит в картину и что он делает; он удаляет студент с идентификатором 1, а также соответствующий объект руководства (идентификатор 1). Но в этом примере есть еще один объект student, который сопоставляется с той же записью guide и если мы не используем orphanRemoval=true атрибут в сущности руководства, код удаления выше не будет работать.
разница:
- orphanRemoval = true:" дочерний " объект удаляется, когда на него больше нет ссылки (его родитель не может быть удален).
- CascadeType.Удалить:" дочерний "объект удаляется только тогда, когда его" Родительский " удаляется.