JPA 2.0 orphanRemoval=true VS On delete Cascade


Я немного запутался в JPA 2.0 .

Я думаю, что вижу, что это необходимо, когда я использую инструменты генерации DB моего провайдера JPA для создания базовой базы данных DDL, чтобы иметь ON DELETE CASCADE о конкретном отношении.

однако, если БД существует и она уже имеет ON DELETE CASCADE по отношению, это не достаточно, чтобы надлежащим образом каскадное удаление? Что значит orphanRemoval сделать в дополнение?

Ура

7 133

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 также автоматически добавляет удалить в каскадный список.

эквивалентное отображение JPA для DDL ON DELETE CASCADE и 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     Roy ECE 1

2 Ник ECE 1

таблица направляющего выступа: -

ID имя зарплата

1 Джон $ 1500

а теперь, если я хочу удалить одного из студентов, используя

      Student student1 = em.find(Student.class,1);
      em.remove(student1);

и когда запись студента удаляется соответствующая запись руководства также должна быть удалена, вот где каскад.Удалить атрибут в сущности Student входит в изображение и то, что он делает; он удаляет студент с идентификатором 1, а также соответствующий объект руководства (идентификатор 1). Но в этом примере есть еще один объект student, который сопоставляется с той же записью руководства, и если мы не используем orphanRemoval=true атрибут в сущности руководства, код удаления выше не будет работать.

разница:
- orphanRemoval = true:" дочерняя " сущность удаляется, когда на нее больше не ссылаются (ее родитель не может быть удален).
- CascadeType.Удалить:" дочерний "объект удаляется только при удалении его" родительского " объекта.