JPA OneToMany 级联更新/删除

Tec*_*ast 4 java database spring hibernate jpa

我有两个实体“文章”和“评论”。文章与评论具有一对多关系。

@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;
}
Run Code Online (Sandbox Code Playgroud)

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

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

article_id         title        category 

     1       Java 8 in 30 days    Java
Run Code Online (Sandbox Code Playgroud)

我有两条评论,“评论”表中的数据如下。

comment_id   author    text              article_id

    1         ABC     Java is awesome !        1
    2         XYZ     Nice Article !!!         1
Run Code Online (Sandbox Code Playgroud)

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

public Article update(Article article)
{
    return entityManager.merge(article);
}
Run Code Online (Sandbox Code Playgroud)

我在这里面临的问题是,每当我使用上述方法调用从现有文章中删除评论时,该评论实际上不会从表中删除。我知道“合并”与“upsert”相同,但我在EntityManager接口中没有找到任何其他方法来实现评论删除以及对文章的其他更改。

aUs*_*elf 5

在您的代码中,@OneToMany(... cascade = CascadeType.ALL)意味着每当对父级进行修改(保留、删除等)时,它也会级联到子级。Article因此,如果保存了一个,则其所有对应的都Comments将被保存。Article或者,如果删除一个,则其所有对应的都Comments将被删除。

就您而言,您想要的只是删除 a Comment,与其' 中发生的操作无关Article

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

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
Run Code Online (Sandbox Code Playgroud)

确保您的集合是唯一持有对 所引用的对象的引用的集合targetComment,否则内存中将出现不一致。