Как вы уже догадались, и, как говорит Javadoc, cascade
операции, которые должны быть каскадно направлены к цели ассоциации ". Однако, убедитесь, что вы понимаете, что mappedBy
определяет сущность-владельца отношений.Владелец объекта - это объект, который фактически выполняет постоянные операции, если он не переопределен настройкой каскада. В этом случае Child
является владельцем объекта.
@Entity
public class Parent {
@Id @GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
@OneToMany(mappedBy="parent")
private Set<Child> children;
Настройка каскада в Parent
работает, когдавы создаете Set
дочерних элементов и устанавливаете его в Parent
, а затем сохраняете Parent
. Затем операция сохранения будет каскадно переходить от Parent
к children
. Это более типичное и ожидаемое использованиев случае настройки * 1013. * Однако это приводит к тому, что операции с базой данных выполняются автоматически, и это не всегда хорошо.
Настройка Каскад для дочернего элемента произойдет, когда дочерний элемент будет сохранен, поэтомувы можете поместить туда cascade
аннотацию, но читайте дальше ...
@Entity
public class Child {
@Id @GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
@ManyToOne(cascade=CascadeType.ALL)
private Parent parent;
Вы сохраните и родителя, и ребенка, сохранивchild.
tx.begin();
Parent p = new Parent();
Child c = new Child();
c.setParent(p);
em.persist(c);
tx.commit();
, и когда вы удаляете дочерний элемент, он удаляет и родителя, и дочерний элемент.
tx.begin();
Child cFound = em.find(Child.class, 1L);
em.remove(cFound);
tx.commit();
em.clear();
именно здесь у вас возникают проблемы.Что произойдет, если у вас более одного ребенка?
em.clear();
tx.begin();
p = new Parent();
Child c1 = new Child();
Child c2 = new Child();
c1.setParent(p);
c2.setParent(p);
em.persist(c1);
em.persist(c2);
tx.commit();
Все хорошо, пока вы не удалите одну из children
em.clear();
tx.begin();
cFound = em.find(Child.class, 2L);
em.remove(cFound);
tx.commit();
, тогда вы получите integrity constraint violation
, когдакаскад распространяется на Parent
, но в базе данных еще есть секунда Child
.Конечно, вы могли бы вылечить это, удалив всех детей в одном коммите, но это немного запутанно, не так ли?
Концептуально люди склонны думать, что распространение идет от Parent
до Child
, и поэтомуочень нелогично иметь это иначе.Далее, как насчет ситуации, когда вы не хотите удалять автора только потому, что магазин продал все его или ее книги?В этом случае вы можете смешивать каскад, иногда от ребенка к родителю, а в других случаях от родителя к ребенку.
Обычно я думаю, что лучше быть очень точным в коде вашей базы данных.Гораздо проще читать, понимать и поддерживать код, который в первую очередь сохраняет родителя, а затем потомка или потомков, чем когда-либо делать аннотацию, о которой я могу знать, а может и не знать, что неявно выполняет дополнительные операции с базой данных.