Hibernate 多对多级联删除

Hibernate 多对多级联删除,hibernate,jpa,Hibernate,Jpa,我有多对多用于标签软件,当我删除标签时,我想删除与该标签相关但与另一个标签无关的所有软件。这里的业务逻辑如下:没有标签的软件不可能存在。下面有两个类和一个测试的代码 现在它删除所有软件,即使它们与其他标签相关 如何处理 @Entity public class Tag extends Model { @Column(nullable = false, unique = true) public String title; public Tag(String title

我有多对多用于标签软件,当我删除标签时,我想删除与该标签相关但与另一个标签无关的所有软件。这里的业务逻辑如下:没有标签的软件不可能存在。下面有两个类和一个测试的代码

现在它删除所有软件,即使它们与其他标签相关

如何处理

@Entity
public class Tag extends Model {

    @Column(nullable = false, unique = true)
    public String title;

    public Tag(String title) {
        this.title = title;
    }

    @ManyToMany(cascade = CascadeType.ALL, mappedBy = "tags")
    public List<Software> softwares = new LinkedList<Software>();

}


@Entity
public class Software extends Model {

    public String title;
    public String description;

    @ManyToOne(optional = false)
    public Author author;

    @ManyToMany
    public List<Tag> tags = new LinkedList<Tag>();

    public Software(String title, String description, Author author) {
       this.title = title;
       this.description = description;
       this.author = author;
    }


    public Software(String title, String description, Author author, Tag ... tags) {
        this(title, description, author);


        if (!Arrays.asList(tags).contains(null)) {

            // it needed if we wand to delete Tags with cascade - when delete Tag, then delete all Softwares related to it
            for (Tag tag : tags) {
               this.tags.add(tag);
            }

            for (Tag tag : tags) {
                tag.softwares.add(this);
            }
        }
    }

 }

触发器或服务层中的逻辑是实现它的最佳选择。如果您真的想通过模型实现它,请对其进行规范化,在这里您可以选择删除时的行为。

触发器,或者服务层中的逻辑是实现它的最佳选择。如果您确实希望通过模型将其规范化,那么您可以在删除时的行为中进行选择。

您所追求的是,当不再有任何引用将软件记录连接到标记记录时,软件记录将被删除,这与
delete\u ORPHAN
级联类型所给出的类似,但我不认为
@ManyToMany
支持这一点


正如Alexis所指出的,您可以通过数据库触发器来实现这一点,但另一种方法可能是使用。

您所追求的是,当不再有任何引用将软件记录连接到标记记录时,软件记录将被删除,这与
DELETE\u ORPHAN
级联类型所给出的类似,但我不认为
@ManyToMany
支持这一点


正如Alexis所指出的,您可以通过数据库触发器来实现这一点,但另一种方法可能是使用。

您的问题似乎令人困惑。您正在删除所有软件上的标记和断言?我只是检查一下,然后应该保留一(1)个软件,因为我认为它也与标记2相关。所以当我删除tag1时-标题为1的软件应该被删除,但标题为3的软件不应该被删除。你能在tag1.delete()之前断言吗?看看你得到了什么样的结果?如果把断言放在前面,那么它会显示:失败,预期的:但是是:你的问题似乎令人困惑。您正在删除所有软件上的标记和断言?我只是检查一下,然后应该保留一(1)个软件,因为我认为它也与标记2相关。所以当我删除tag1时-标题为1的软件应该被删除,但标题为3的软件不应该被删除。你能在tag1.delete()之前断言吗?看看你得到了什么结果?如果把assert放在前面,那么它会显示:Failure,expected:但是was:是的,不幸的是,它在多对多中不受支持。我倾向于认为,不要依赖于级联(去掉级联),而是在DAO层中执行添加操作onDelete,这样可以处理关系,然后就可以删除了。(我尝试不处理触发器或额外的逻辑id数据库端)是的,不幸的是,它在多对多中不受支持。我倾向于认为,不要依赖于级联(去掉级联),而是在DAO层中执行添加操作onDelete,这样可以处理关系,然后就可以删除了。(我尝试不处理触发器或额外的逻辑id数据库端)
@Test
public void testDelete() throws InterruptedException {

    Tag tag1 = new Tag("tag1").save();
    Tag tag2 = new Tag("tag2").save();

    Author author1 = new Author("name", "email").save();


    new Software("title1", "description1", author1, tag1).save();

    new Software("title3", "description3", author1, tag1, tag2).save();


    tag1.delete();

    // try to find the software
    assertEquals(1, Software.findAll().size());  // IT FAILS - IT DELETES ALL
}