JPA级联更新/删除OneToMany

时间:2017-11-03 08:29:27

标签: java database spring hibernate jpa

我有两个实体“文章”和“评论”。文章与评论有OneToMany关系。

@Entity
@Table(name = "article")
public class Article implements Serializable
{
    public Article()
    {

    }
    private static final long serialVersionUID = 1L;
    @Id
    @Column(name = "article_id")
    private int articleId;
    @Column(name = "title")
    private String title;
    @Column(name = "category")
    private String category;
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "articleId", cascade = CascadeType.ALL)
    private List<Comment> comments = new ArrayList<>();
}


@Entity
@Table(name = "comment")
public class Comment
{
    private static final long serialVersionUID = 1L;
    public Comment()
    {

    }
    @Id
    @Column(name = "comment_id")
    private int commentId;
    @Column(name = "author")
    private String author;
    @Column(name = "text")
    private String text;

    @JoinColumn(name = "article_id", nullable = false)
    private int articleId;
}

我正在使用JPA EntityManager对Article执行CRUD操作。

我在“文章”表格中有一篇文章包含以下数据。

article_id         title        category 

     1       Java 8 in 30 days    Java

我对“评论”表中的以下数据有两条评论。

comment_id   author    text              article_id

    1         ABC     Java is awesome !        1
    2         XYZ     Nice Article !!!         1

这是我的EntityManager代码,当包含评论的文章发布更新时会调用该代码。

public Article update(Article article)
{
    return entityManager.merge(article);
}

我在这里面临的问题是,每当我使用上述方法调用从现有文章中删除评论时,评论确实不会从表中删除。我理解“merge”与“upsert”相同,但我没有在EntityManager界面中找到任何其他方法来实现注释删除以及对文章的其他更改。

1 个答案:

答案 0 :(得分:2)

在您的代码中,@OneToMany(... cascade = CascadeType.ALL)表示无论何时对父级进行修改(持久,删除等),它都会级联到子级。因此,如果保存了Article,则会保存其相应的Comments。或者,如果删除了Article,则会删除其相应的Comments

在您的情况下,您想要的只是删除Comment,与其Article中发生的操作无关。

一种简单的方法是使用@OneToMany(... cascade = CascadeType.ALL, orphanRemoval = true),然后当您决定在第一个delete上触发Comment时,只需在其上使用Collection.remove():< / p>

Article article = ...;
//...
Comment targetComment = article.getComments().iterator().next();
article.getComments().remove(targetComment);
// now Hibernate considers `targetComment` as orphan and it executes an SQL DELETE for it

确保您的收藏集是唯一一个持有targetComment引用的对象引用的收藏集,否则您的内存将会出现不一致。