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.Удалить:" дочерний "объект удаляется только тогда, когда его" Родительский " удаляется.