Java 如何在多对多关系中使用休眠和 JPA 删除孤立实体?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3055407/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 16:02:56  来源:igfitidea点击:

How do I delete orphan entities using hibernate and JPA on a many-to-many relationship?

javasqlhibernatejpa

提问by Alucard

I want to delete orphan entities using hibernate and JPA on a many-to-many relationship but all that I found was this attribute the attribute. org.hibernate.annotations.CascadeType.DELETE_ORPHAN ( i.e. @Cascade(value={org.hibernate.annotations.CascadeType.DELETE_ORPHAN) ), which works only for one-to-many relationships.

我想在多对多关系中使用 hibernate 和 JPA 删除孤立实体,但我发现的只是这个属性。org.hibernate.annotations.CascadeType.DELETE_ORPHAN(即@Cascade(value={org.hibernate.annotations.CascadeType.DELETE_ORPHAN)),仅适用于一对多关系。

I want to know if I can delete the orphan ones on my many-to-many relationship.

我想知道是否可以删除多对多关系中的孤儿。

回答by Pascal Thivent

Actually, I did a test with the following entities:

实际上,我对以下实体进行了测试:

@Entity
public class Person {
    @Id
    @GeneratedValue
    private Long id;
    private String firstName;
    private String lastName;

    @ManyToMany
    @Cascade(value = org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
    private Set<Role> roles = new HashSet<Role>();

    //...
}

@Entity
public class Role {
    @Id
    @GeneratedValue
    private Long id;

    private String name;

    @ManyToMany(mappedBy = "roles")
    private Set<Person> persons = new HashSet<Person>();

    //...
}

And with the following dataset:

并使用以下数据集:

<dataset>
    <PERSON id="1" firstname="john" lastname="doe"/>
    <PERSON id="2" firstname="clark" lastname="kent"/>
    <PERSON id="3" firstname="james" lastname="bond"/>
    <ROLE id="1" name="foo"/>
    <ROLE id="2" name="bar"/>
    <ROLE id="3" name="boo"/>
    <ROLE id="4" name="baz"/>
    <PERSON_ROLE persons_id="1" roles_id="1"/>
    <PERSON_ROLE persons_id="1" roles_id="2"/>
    <PERSON_ROLE persons_id="2" roles_id="2"/>
    <PERSON_ROLE persons_id="2" roles_id="3"/>
    <PERSON_ROLE persons_id="3" roles_id="1"/>
    <PERSON_ROLE persons_id="3" roles_id="4"/>
</dataset>

The following test method:

以下测试方法:

@Test
public void testCascadeDeleteOrphanOnDelete() {
    Person person = entityManager.find(Person.class, 1L);
    entityManager.remove(person);
    ReflectionAssert.assertPropertyLenientEquals("id", Arrays.asList(2, 3), findAllPersons());
    ReflectionAssert.assertPropertyLenientEquals("id", Arrays.asList(3, 4), findAllRoles());

}

private List<Person> findAllPersons() {
    return entityManager.createQuery("from Person").getResultList();
}

private List<Role> findAllRoles() {
    return entityManager.createQuery("from Role").getResultList();
}

Just passes. Below the produced output:

刚刚通过。在生成的输出下方:

Hibernate: select personx0_.id as id17_0_, personx0_.firstName as firstName17_0_, personx0_.lastName as lastName17_0_ from Person personx0_ where personx0_.id=?
Hibernate: select roles0_.persons_id as persons1_1_, roles0_.roles_id as roles2_1_, rolex1_.id as id18_0_, rolex1_.name as name18_0_ from Person_Role roles0_ left outer join Role rolex1_ on roles0_.roles_id=rolex1_.id where roles0_.persons_id=?
Hibernate: delete from Person_Role where persons_id=?
Hibernate: delete from Role where id=?
Hibernate: delete from Role where id=?
Hibernate: delete from Person where id=?
Hibernate: select personx0_.id as id17_, personx0_.firstName as firstName17_, personx0_.lastName as lastName17_ from Person personx0_
Hibernate: select rolex0_.id as id18_, rolex0_.name as name18_ from Role rolex0_

回答by demonz demonz

try this:

尝试这个:

@ManyToMany(cascade = CascadeType.ALL, orphanRemoval=true, fetch = FetchType.LAZY, mappedBy = "yourObject")

回答by ichalos

So far there is no orphanRemovalattribute for the ManyToMany annotation. I have the same problem too. And the suggestion to implement it to on the database is no answer to the problem. The whole philosophy of JPA is againstimplementing logic on the database, but through the mappings.

到目前为止,ManyToMany 注释没有orphanRemoval属性。我也有同样的问题。而在数据库上实施它的建议并不能解决问题。JPA 的整个理念是反对在数据库上实现逻辑,而是通过映射。

回答by HDave

From the book "Pro JPA 2":

来自“Pro JPA 2”一书:

Only relationships with single cardinality on the source side can enable orphan removal, which is why the orphanRemoval option is defined on the @OneToOne and @OneToMany relationship annotations, but on neither of the @ManyToOne or @ManyToMany annotations.

只有在源端具有单一基数的关系才能启用孤儿移除,这就是为什么在@OneToOne 和@OneToMany 关系注释上定义了 orphanRemoval 选项,但在@ManyToOne 或@ManyToMany 注释上都没有定义。

It's a bummer, but there is no JPA automated orphan removal for ManyToMany.

这是一个无赖,但ManyToMany 没有JPA 自动孤儿删除。