2011-06-02 36 views
2

以下是博客帖子型号:如何删除一个部件为空时的ManyToMany相关对象?

@Entity 
@Table(name = "blog_posts") 
public class BlogPost extends Model { 
    @Required 
    @MaxSize(50) 
    @MinSize(3) 
    @Column(length=50) 
    public String title; 

    @Lob 
    @Required 
    @MaxSize(10000) 
    public String description; 

    @Temporal(TemporalType.TIMESTAMP) 
    public Date created; 

    @ManyToMany(targetEntity=PostTag.class, cascade=CascadeType.DETACH) 
    @OrderBy("name ASC") 
    public List<PostTag> tags; 

     // + other fields 
} 

而且PostTag:

@Entity 
@Table(name = "post_tags") 
public class PostTag extends Model { 
    @Match("^([a-zA-Z0-9\\-]{3,25})$") 
    @MinSize(3) 
    @MaxSize(25) 
    @Required 
    @Column(length=25, unique=true) 
    public String name; 

    @ManyToMany(targetEntity=BlogPost.class, mappedBy="tags", cascade=CascadeType.REMOVE) 
    public List<BlogPost> posts; 
} 

的关系正常,但希望我是,当我从我的文章中删除标签,如果没有其他职位使用此标签,然后我可以从我的数据库中删除它。

这是我试过的代码,而是生成一个休眠例外:

public boolean removeTag(PostTag tag) { 
    if (!tags.contains(tag)) { 
     return false; 
    } 

    tags.remove(tag); 
    save(); 

    if (tag.posts == null || tag.posts.isEmpty()) { 
     tag.delete(); 
    } 

    return true; 
} 

确切的例外是:

org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update 

java.sql.BatchUpdateException: Cannot delete or update a parent row: a foreign key constraint fails 

我试图CascadeType的改变DELETE_ORPHANS,但它的过时,而新版本似乎只适用于OneToOne和OneToMany关系:/

我该怎么办?

感谢您的帮助!

+0

如果我正确地考虑一个标签,它不会是一个OneToMany与帖子的关系?一个标签(对象),很多帖子。 – 2011-06-02 13:41:45

+0

我想过这样做,但是使用ManyToMany,我可以在Post中拥有一个标签列表,并且可以在Tags表中使用唯一标签。 – 2011-06-02 13:43:41

+1

使用OneToMany/ManyToOne,您仍然可以拥有Post中的标签列表。您删除标签的逻辑会改变。一个更好的方式去实现这将是有一个标签与大量的帖子相关,并保持标签周围,无论帖子是否使用它。只有在被请求时才删除标签。这是大多数博客系统的工作原理。除非你有必要建立一个ManyToMany关系。 – 2011-06-02 13:59:57

回答

2

好的我发现问题出在哪里,所以我会在这里解释一下,以防有人遇到同样的问题。

这个例外是因为我试图删除一个仍然存在关系的标签(它并不是独立存在)。

这里是如何删除标签一个可行的解决方案时,有没有帖子使用它了:

public boolean removeTag(PostTag tag) { 
    if (!tags.contains(tag)) { 
     return false; 
    } 

    tags.remove(tag); 
    save(); 

    if (PostTag.find("name = ? AND size(posts) = 0", tag.name).first() != null) { 
     tag.delete(); 
    } 

    return true; 
} 
0

由于您使用的是双向的关系,你应该更新了“反向”

public boolean removeTag(PostTag tag) { 
    if (!tags.contains(tag)) { 
     return false; 
    } 

    tags.remove(tag);  //  remove post -> tag link 

    tag.posts.remove(this); // added: remove tag -> post link 

    save(); 

    if (tag.posts == null || tag.posts.isEmpty()) { 
     tag.delete(); 
    } 

    return true; 
} 
相关问题