簡體   English   中英

從 spring jpa 中的表(具有父子關系的自引用表)中刪除數據時出錯

[英]Error while deleting data from table (self referencing table with parent-child relation) in spring jpa

我有一個與自身有層次關系的實體 class 名稱注釋。

@Entity
@Table(name = "comment")
public class Comment implements java.io.Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "document", nullable = false)
    private Document document;

    @Column(name = "threadid")
    private String threadId;

    @Column(name = "code")
    private String code;

    @Column(name = "content")
    private String content;

    @Column(name = "authorid")
    private String authorId;

    @Column(name = "timestamp")
    private String timeStamp;

    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "parentcomment")
    private ContractComment parentComment;
}

我想刪除文檔的所有評論,但是當我使用 JpaRepository 使用以下查詢時

"delete from Comment where document.id = :documentId"

它給出了以下錯誤。

Cannot delete or update a parent row: a foreign key constraint fails (`comment`, CONSTRAINT `fk_comment_parentcomment` FOREIGN KEY (`parentcomment`) REFERENCES `comment` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION)

我嘗試了這 3 種方法,但總是遇到同樣的錯誤。

    @OneToOne(fetch = FetchType.LAZY, cascade=CascadeType.ALL)
    @JoinColumn(name = "parentcomment")
    private ContractComment parentComment;



    @OneToOne(fetch = FetchType.LAZY, cascade=CascadeType.REMOVE)
    @JoinColumn(name = "parentcomment")
    private ContractComment parentComment;


    @OneToOne(fetch = FetchType.LAZY, orphanRemoval=true)
    @JoinColumn(name = "parentcomment")
    private ContractComment parentComment;

您需要添加@OneToOne(fetch = FetchType.LAZY, cascade=CascadeType.REMOVE)而不是@OneToOne(fetch = FetchType.LAZY, cascade=CascadeType=REMOVE)

使用 CriteriaQueries 來處理您的實體,而不是直接 JPQL 查詢。 CriteriaQuery 可能如下所示:

public void deleteComments(Long documentId) {
    CriteriaBuilder cb = this.em.getCriteriaBuilder();

    // create delete
    CriteriaDelete<Comment> delete = cb.
     createCriteriaDelete(Comment.class);

    // set the root class
    Root root = delete.from(Comment.class);

    // set where clause
    delete.where(cb.equal(root.get(Comment_.document).get(Document_.id), documentId));

    // perform update
    this.em.createQuery(delete).executeUpdate();
}

Comment_ class 可用於獲取“評論”實體的所有“列”,因此首先從評論中獲取文檔( root.get(Comment_.document) ),然后獲取文檔的 ID( ...get(Document_.id) ) 並將其與您的參數進行比較。

Criteria Queries 與 JPQL 字符串有點不同,但它們的優點是編譯器可以幫助您在數據庫中實現更改(而 JPQL 查詢只會引發運行時錯誤)

如果您不想使用這樣的查詢,您始終可以在Document class 中實現deleteComments方法。 然后你獲取 Document 並讓 entityManager 處理刪除:

Document doc = entityManager.find(Document.class, documentId);

// and in the Document class:
public void deleteComments(){
    this.comments.stream.forEach( comment-> comment.delete());
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM