Должен ли я разрешить удаление JPA или базы данных каскадом? - PullRequest
12 голосов
/ 26 апреля 2011

Допустим, у нас есть две сущности, A и B. B имеет отношение «многие к одному», как A: 1. 1001 *

@Entity
public class A {
  @OneToMany(mappedBy="a_id")
  private List<B> children;
}

@Entity
public class B {
  private String data;
}

Теперь я хочу удалить объект A и каскадно удалить все его дочерние объекты (B). Есть два способа сделать это:

1) Добавьте cascade=CascadeType.ALL, orphanRemoval=true к аннотации OneToMany, позволяя JPA удалить все дочерние объекты перед удалением A-объекта из базы данных.

2) Оставьте классы такими, какие они есть, и просто позвольте базе данных каскадировать удаление.

Есть ли проблемы с использованием более поздней опции? Приведет ли это к тому, что Entity Manager сохранит ссылки на уже удаленные объекты? Моя причина выбора варианта два над одним состоит в том, что вариант один генерирует n + 1 SQL-запросов для удаления, что может занять продолжительное время, когда объект A содержит много дочерних элементов, в то время как второй вариант генерирует только один SQL-запрос и затем переходит к счастливо. Есть ли какая-либо «лучшая практика» в этом отношении?

Ответы [ 3 ]

6 голосов
/ 26 апреля 2011

В EclipseLink вы можете использовать оба, если вы используете аннотацию @CascadeOnDelete. EclipseLink также сгенерирует каскадный DDL для вас.

См, http://wiki.eclipse.org/EclipseLink/Examples/JPA/DeleteCascade

Это оптимизирует удаление, позволяя базе данных делать это, но также поддерживает кэш и единицу сохранения, удаляя объекты.

Обратите внимание, что orphanRemoval = true также удалит объекты, удаленные из коллекции, что не подойдет для вас каскадным ограничением базы данных, поэтому наличие правил в JPA все еще необходимо. Существуют также некоторые отношения, для которых база данных не может обработать удаление, поскольку база данных может каскадироваться только в обратном направлении ограничения, OneToOne с внешним ключом или OneToMany с таблицей соединений не могут каскадироваться в базе данных.

5 голосов
/ 26 апреля 2011

Я бы предпочел базу данных.Почему?

  • База данных, вероятно, работает намного быстрее
  • База данных должна быть основным местом для хранения информации о целостности и отношениях.JPA просто отражает эту информацию
  • Если вы подключаетесь к другому приложению / платформе (например, без JPA), вы все равно можете каскадно удалять свои записи, что помогает повысить целостность данных
2 голосов
/ 30 августа 2012

Этот ответ выдвигает некоторые действительно веские аргументы о том, почему именно JPA должен обрабатывать каскад, а не базу данных.

Вот соответствующая цитата:

... если бы вы делали каскады в базе данных, а не объявляли их в Hibernate (из-за проблем с производительностью), в некоторых случаях вы можете получить ошибки.Это связано с тем, что Hibernate хранит сущности в своем кеше сеанса, поэтому он не будет знать о том, что база данных удаляет что-либо каскадно.

Когда вы используете кэш второго уровня, ваша ситуация еще хуже, потому что этот кэш живет дольше, чем сеанси такие изменения на стороне базы данных будут невидимы для других сессий, так как длинные старые значения хранятся в этом кэше.

...