簡體   English   中英

Spring JPA從新的子實體合並父實體

[英]Spring JPA merge parent entity from new child entity

我搜索了SO並沒有為此找到合適的解決方案。 假設我有一個父實體:

@Entity
public class Parent {
    @Id
    @GeneratedValue
    private int id;

    @OneToMany(mappedBy = "parent", cascade = CascadeType.REMOVE)
    private List<Child> childList;
}

和子實體,它具有與父實體關聯的外鍵:

@Entity
public class Child {
    @Id
    @GeneratedValue
    private int id;

    @JoinColumn(name = "parentId")
    @ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    private Parent parent;

}

我的場景有點特別。 子實體每小時生成一次,我需要將它們保存到數據庫中。 這些子對象可以具有相同的父對象,並且關聯父實體可能已經存在於數據庫中。 我的要求是保存所有這些子對象而不從entityManager中查詢托管父實體,如果父實體存在,則只需合並/更新現有實體。 如:

Child c = new Child();
// set some properties of child
Parent p = new Parent();
// set some properties from my data into the parent. The parent may already exists
child.setParent(p);
JpaRepo.saveAndFlush(child);// If parent already exists, merge with the existed parent object, otherwise, create new parent object.

顯然這不起作用。 當父實體不存在時,它將正確創建父實體並與之關聯。 但是如果父元素已經存在,它將拋出關於重復鍵的異常,如果我設置父元素的Id(使用虛擬值強制使其通過合並),它將拋出分離的實體對象的異常。

由於性能限制,我無法從數據庫加載父實體,因為它們太多了。 那么當主鍵違反時,有沒有辦法自動為JPA或數據庫合並對象?

我正在使用MySQL,是否可以使用ON DUPLICATE KEY UPDATE?

你想要實現的是一個有點棘手的工作人員。 如果延遲加載等不是一個選項(我更喜歡),我建議您創建另一個實體:

@Entity
@Table(name = "sameAsTheOriginal")
public class ChildSaveObject {
    @Id
    @GeneratedValue
    private int id; //I think int will run out fast if there are a lot of objects but it is your choice. (Int max value: 2 147 483 647 is not that mutch) I prefer Long az id

    @Column(name = "parentId")
    private int parent; //note that You need to have the id of the parent object

    //Other properties...
}

在此流程中,您必須檢查父對象是否存在,並使用ChildSaveObject將其他子項保存到該對象。

在大多數情況下,我並不喜歡一對多的映射,我認為它們只是很多問題的根源。 如果您更喜歡這種方式,我建議使用fetch = FetchType.LAZY並獲取父實體(這樣它就不會加載您不需要的所有子項)。

暫無
暫無

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

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