many-to-many cascade delete
I have many-to-many for tag <-> software, when i delete tag i want delete all softwares which are related to that tag BUT not which are related to another tag. The business logic here is the following: Sofware can not exist without a tag. There are code with two classes and one test below.
Now it deletes all softwares even if they are related to other tags.
How to handle it?
@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);
}
}
}
}
there is a test:
@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
}
Triggers, or logic in your service layer is the best bet to achieve it. If you really want it via model, normalize it, here you have a choice to do in the behavior on delete.
What you're after, that a software record is deleted when there are no longer any references joining it to a tag record, is similar to what's given by the DELETE_ORPHAN
cascade type, but I don't think that's supported for @ManyToMany
.
As Alexis notes, you can accomplish this by database triggers, but another approach might be to use interceptors or events.
精彩评论