Должен ли я разрешить удаление 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 будут быть невидимым для других сеансов, поскольку старые старые значения хранятся в этом Кэш.