2016-07-18 9 views
1

Ich habe die SO gesucht und habe keine geeignete Lösung dafür gefunden. Sagen, dass ich eine Muttergesellschaft haben:Spring JPA merge übergeordnete Entität von neuen untergeordneten Entität

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

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

Und ein Kind Einheit, die mit der Muttergesellschaft zugeordnet Fremdschlüssel haben:

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

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

}

Mein Szenario etwas Besonderes ist. Die untergeordnete Entität wird jede Stunde in einer großen Menge generiert und ich müsste sie in der Datenbank speichern. Diese untergeordneten Objekte können dieselben übergeordneten Elemente haben, und die zugehörige übergeordnete Entität ist möglicherweise bereits in der Datenbank vorhanden. Meine Anforderung besteht darin, alle diese untergeordneten Objekte zu speichern, ohne die verwaltete übergeordnete Entität von entityManager abzufragen. Wenn die übergeordnete Entität vorhanden ist, muss nur die vorhandene übergeordnet werden. Wie zum Beispiel:

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. 

Offenbar funktioniert das nicht. Wenn die übergeordnete Entität nicht vorhanden ist, wird die übergeordnete Entität korrekt erstellt und ihr zugeordnet. Aber wenn der Elternteil bereits existiert, wird eine Ausnahme über einen doppelten Schlüssel ausgelöst, und wenn ich die ID des Elternteils festlege (benutze einen Dummy-Wert, um die Fusion zu erzwingen), wird eine Ausnahme des gelöschten Entitätsobjekts ausgelöst.

Aufgrund der Leistungseinschränkung kann ich die übergeordnete Entität nicht aus der Datenbank laden, da zu viele davon vorhanden sind. Gibt es also eine Möglichkeit, JPA oder die Datenbank automatisch mit dem Objekt zu verbinden, wenn der Primärschlüssel verletzt wird?

Ich benutze MySQL, ist das möglich, ON DUPLICATE KEY UPDATE zu verwenden?

+0

Haben Sie die Eltern-ID vor dem Speichern mit dem Child-Objekt verfügbar? –

+0

Nein, ich habe keine ID, aber stattdessen habe ich alle Attribute, die als eindeutiger Schlüssel zur Identifizierung des Objekts verwendet werden können. – LynxZh

Antwort

0

Es ist ein bisschen schwierig Personal, das Sie gerne erreichen möchten. Wenn ein träges Laden usw. ist keine Option (die ich lieber) empfehle ich Ihnen eine andere Entität erstellen:

@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... 
} 

In diesem Fluss müssen Sie prüfen, ob das übergeordnete Objekt existiert und die ChildSaveObject benutzen, um Ihr weiteres Kind zu retten zu ihm.

Ich mag in den meisten Fällen nicht eine bis viele Abbildungen, ich denke, dass sie nur Wurzeln vieler Probleme sind. Dennoch, wenn Sie diesen Weg bevorzugen, ist meine Empfehlung, fetch = FetchType.LAZY zu verwenden und die übergeordnete Entität zu erhalten (auf diese Weise lädt es nicht alle Kinder, die Sie nicht benötigen).

+0

Ich werde das Kind nicht von Eltern laden. Die Sache ist, dass ich ein neues Kind erstellen muss und einem vorhandenen Elternteil zugeordnet werden muss, ODER, erstellen Sie das neue Elternelement, wenn es nicht existiert. – LynxZh

+0

Deshalb sollten Sie prüfen, ob der Elternteil existiert. Sie führen eine Abfrage aus, um das übergeordnete Element abzurufen, und wenn es sich um ein nicht vorhandenes Element handelt, erstellen Sie eines, andernfalls legen Sie das minimierte Element fest. – Mark

Verwandte Themen