2016-04-21 11 views
0

In Ordnung, ich bin ein wenig depreate jetzt. Ich habe viele der anderen verwandten Fragen gelesen, aber das hat mir noch nicht geholfen, mein Problem zu lösen. Ich bin froh, wenn mir jemand helfen kann.Richtig kaskadieren diese @ OneToMany-Beziehung (Spring Data JPA)

Ich verwende Spring Data JPA, und ich habe diese beiden Entitäten:


Device.class

private String id; 

@OneToMany(mappedBy = "device", cascade = CascadeType.ALL) 
@JsonIgnore 
@RestResource(exported = false) 
private List<Reading> readings; 

Reading.class

@ManyToOne(cascade = {CascadeType.MERGE}) /*This isn't right...*/ 
@JoinColumn(name = "device_id") 
private Device device; 

Erwartung

ich nur Lesungen und erwarten, dass die Geräte werden richtig kaskadiert (beharrte oder fusionierten) bin zu speichern, je nachdem, ob es bereits vorhanden ist. (Die Messwerte werden nur einmal eingesetzt, sie werden nie aktualisiert)

Reality

ich nur diese Arbeit machen kann teilweise:

Wenn ich cascade = CascadeType.ALL oder cascade = CascadeType.PERSIST verwenden kann ich die erste speichern Lesen und zugeordnetes Gerät Sobald ich eine zweite Lesung einzufügen, das eine Beziehung zu dem gleichen Gerät hat, bekomme ich etwas entlang der Linien von:

Duplicate entry '457129' for key 'PRIMARY' 
('457129' = Reading.Device.id) 

Wie ich verstehe, versuchen die zweite Lese Unternehmen seine Geräte kaskadieren, indem eine neue Zeile einzufügen statt Aktualisierung der bestehenden.

Ich kann "umgehen" dies mit cascade = CascadeType.MERGE stattdessen. Jetzt wird das Gerät korrekt aktualisiert, wenn ich eine neue Lesung mit einer vorhandenen Geräteentität speichere. ABER jetzt kann ich kein Gerät mehr kaskadieren, das noch nicht existiert!

Column 'device_id' cannot be null 
(Reading.device_id) 

Das Speichern

I erhalten JSON DTO und die Entitäten daraus erstellen.

Pseudocode:

Reading reading = deserialize(jsonReading); 
Device device = deserialize(device); 

reading.setDevice(device); /* Device entity is detached */ 

readingService.save(reading); 

Ich denke, ein Teil des Problems bei mir vielleicht zu tun haben, eine freistehende Einheit einstellen?

Was mache ich falsch? Sind meine Beziehungen schlecht? Was ist los? Muss ich diese Transaktionen manuell verwalten?

Vielen Dank!

Antwort

0

Die @OneToMany-Assoziation ist definitionsgemäß eine übergeordnete Zuordnung, auch wenn sie unidirektional oder bidirektional ist. Nur die Elternseite einer Assoziation ist sinnvoll, um ihre Entitätsstatusübergänge auf untergeordnete Elemente zu kaskadieren. (Quelle: Hibernate docs).

Basierend auf der Dokumentation werde ich die cascade aus dem Feld device entfernen. Docs enthält auch Codebeispiele zum Speichern von Phone und Person für @OneToMany und @ManyToOne, die Sie versuchen können.

Wie Sie Teil keinen Code schreiben hat zum Speichern Ich nehme an, dass Sie Gerät einstellen, bevor automatisch die reading als

reading.setDevice(device); 
readingDao.save(reading); // depends on your implementation 

Wenn persistierende reading Objekt der device gespeichert werden sollen sparen.

+0

Ich entfernte die "Kaskade", aber das half nicht. Immer noch "Spalte" device_id "kann nicht null sein". Ich fügte der Frage auch den sparenden Teil hinzu, da es wichtig sein könnte. – sldk

+0

Haben Sie Primärschlüssel mit '@ Id' Annotation definiert? Wenn Sie neue Objekte erstellen, lassen Sie die ID-Werte unverändert und verwenden Sie sie beim Aktualisieren (aber rufen Sie 'saveOrUpdate' in der Dao-Implementierung anstelle von' save' auf) –

+0

Ja. '' @Id @GeneratedValue private int id; '' 'Reading''. '' @Id private String-ID; '' '' Device''. – sldk