JPA: однонаправленное много-к-одному и каскадное удаление
скажем, у меня есть однонаправленный@ManyToOne
отношения следующим образом:
@Entity
public class Parent implements Serializable {
@Id
@GeneratedValue
private long id;
}
@Entity
public class Child implements Serializable {
@Id
@GeneratedValue
private long id;
@ManyToOne
@JoinColumn
private Parent parent;
}
если у меня есть родитель P и дети C1...Cn возвращаясь к P, есть ли чистый и красивый способ в JPA автоматически удалять детей C1...Cn когда P удаляется (т. е. entityManager.remove(P)
)?
то, что я ищу-это функциональность, аналогичную ON DELETE CASCADE
в SQL.
4 ответа:
отношения в JPA всегда однонаправленные, если вы не связываете родителя с дочерним в обоих направлениях. Каскадирование операций удаления от родителя к ребенку потребует отношения от родителя к ребенку (а не наоборот).
поэтому вам нужно сделать это:
- либо измените однонаправленный
@ManyToOne
отношение к двунаправленному@ManyToOne
, или однонаправленным@OneToMany
. Затем вы можете каскадировать операции удаления так этоEntityManager.remove
удалить родителя и детей. Вы также можете указатьorphanRemoval
как true, чтобы удалить всех осиротевших детей, когда дочерняя сущность в родительской коллекции имеет значение null, т. е. удалить ребенка, когда он не присутствует в родительской коллекции.- или укажите ограничение внешнего ключа в дочерней таблице как
ON DELETE CASCADE
. Вам нужно будет вызватьEntityManager.clear()
после вызоваEntityManager.remove(parent)
как настойчивость контекст должен быть обновлен - дочерние сущности не должны существовать в контексте сохраняемости после их удаления в базе данных.
Если вы используете hibernate в качестве поставщика JPA, вы можете использовать аннотацию @OnDelete. Эта аннотация добавит к отношению триггер ON DELETE CASCADE, который делегирует удаление дочерних элементов в базу данных.
пример:
public class Parent { @Id private long id; } public class Child { @Id private long id; @ManyToOne @OnDelete(action = OnDeleteAction.CASCADE) private Parent parent; }
С помощью этого решения однонаправленной связи от дочернего элемента к родительскому достаточно, чтобы автоматически удалить все дочерние элементы. Это решение не нуждается в слушателях и т. д. Также запрос удалить из родителя, где id = 1 удалить детей.
создайте двунаправленную связь, например:
@Entity public class Parent implements Serializable { @Id @GeneratedValue private long id; @OneToMany(mappedBy = "parent", cascade = CascadeType.REMOVE) private Set<Child> children; }
@ Cascade (org.зимовать.комментарии.CascadeType.DELETE_ORPHAN)
данная аннотация работала на меня. Можете попробовать
Например:
public class Parent{ @Id @GeneratedValue(strategy=GenerationType.AUTO) @Column(name="cct_id") private Integer cct_id; @OneToMany(cascade=CascadeType.REMOVE, fetch=FetchType.EAGER,mappedBy="clinicalCareTeam", orphanRemoval=true) @Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN) private List<Child> childs; } public class Child{ @ManyToOne(fetch=FetchType.EAGER) @JoinColumn(name="cct_id") private Parent parent; }