Скажем, у меня однонаправленные @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 и дочерние C 1 ... C n, ссылающиеся на P, есть ли в JPA чистый и красивый способ автоматического удаления дочерних C 1 ... C n при удалении P (т.е. entityManager.remove(P)
)?
Я ищу функциональность, аналогичную ON DELETE CASCADE
SQL.
java
jpa
jpa-2.0
many-to-one
преступник
источник
источник
Ответы:
Отношения в JPA всегда однонаправлены, если вы не связываете родительский элемент с дочерним в обоих направлениях. Каскадные операции REMOVE от родителя к потомку потребуют отношения от родителя к потомку (а не только наоборот).
Поэтому вам необходимо сделать это:
@ManyToOne
связь на двунаправленную@ManyToOne
, либо на однонаправленную@OneToMany
. Затем вы можете каскадировать операции REMOVE, чтобы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; }
С этим решением однонаправленных отношений от дочернего к родительскому достаточно для автоматического удаления всех дочерних элементов. Это решение не требует никаких слушателей и т. Д. Также запрос типа DELETE FROM Parent WHERE id = 1 удалит потомков.
источник
@OneToOne
Есть идеи, как это решить@OneToOne
?Создайте двунаправленные отношения, например:
@Entity public class Parent implements Serializable { @Id @GeneratedValue private long id; @OneToMany(mappedBy = "parent", cascade = CascadeType.REMOVE) private Set<Child> children; }
источник
Я видел в однонаправленном @ManytoOne, удаление не работает должным образом. Когда родитель удаляется, в идеале дочерний элемент также должен быть удален, но удаляется только родительский элемент, а дочерний элемент НЕ удаляется и остается сиротой.
Используемые технологии: Spring Boot / Spring Data JPA / Hibernate.
Загрузка Sprint: 2.1.2.RELEASE
Spring Data JPA / Hibernate используется для удаления строки .eg
parentRepository.delete(parent)
ParentRepository расширяет стандартный репозиторий CRUD, как показано ниже
ParentRepository extends CrudRepository<T, ID>
Ниже приведен мой класс сущности
@Entity(name = “child”) public class Child { @Id @GeneratedValue private long id; @ManyToOne( fetch = FetchType.LAZY, optional = false) @JoinColumn(name = “parent_id", nullable = false) @OnDelete(action = OnDeleteAction.CASCADE) private Parent parent; } @Entity(name = “parent”) public class Parent { @Id @GeneratedValue private long id; @Column(nullable = false, length = 50) private String firstName; }
источник
spring.jpa.hibernate.use-new-id-generator-mappings=true spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
"
в коде. См.name= "parent"
Используйте этот способ, чтобы удалить только одну сторону
@ManyToOne(cascade=CascadeType.PERSIST, fetch = FetchType.LAZY) // @JoinColumn(name = "qid") @JoinColumn(name = "qid", referencedColumnName = "qid", foreignKey = @ForeignKey(name = "qid"), nullable = false) // @JsonIgnore @JsonBackReference private QueueGroup queueGroup;
источник
@Cascade (org.hibernate.annotations.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; }
источник
Вам не нужно использовать двунаправленную ассоциацию вместо вашего кода, вам просто нужно добавить CascaType.Remove в качестве свойства к аннотации ManyToOne, а затем использовать @OnDelete (action = OnDeleteAction.CASCADE), у меня это отлично работает.
источник