Должен ли я разрешить удаление JPA или каскада базы данных?

Предположим, что у нас есть две сущности: A и B. B имеет отношение много к одному с A следующим образом:

@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-запрос, а затем переходит счастливо. Есть ли "лучшая практика" в этом отношении?

Ответ 1

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

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

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

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

Ответ 2

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

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

Ответ 3

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

Здесь соответствующая цитата:

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

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