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
}