2017-03-20 2 views
1

Ich habe zwei Entitätsklassen Organisation und Benutzer mit einem one to many Beziehung (Groovy-Code für Einfachheit!):Frühling JPA: Einfügen eines neuen Entity und Cascade freistehende Referenz

@Entity 
class Organisation { 
    @Id Long id 
    String name 
    @OneToMany 
    List<User> users 
} 

@Entity 
class User { 
    @Id Long id 
    String username 
    @ManyToOne(optional=false, cascade = CascadeType.Persist) 
    Organisation organisation 
} 

Wenn ich einen neuen Benutzer erstellen mit einer neuen Organisation funktioniert alles einwandfrei:

def user = new User(organisation: new Organisation(...)) 

Aber wenn ich eine bestehende Organisation nehmen, stellen sie es auf die Organisation Attribut auf einen neuen Benutzer ich eine Fehlermeldung erhalten:

def user = new User(organisation: organisationRepository.findOne(orgId)) 
userRepo.save(user) 

bewirkt:

org.hibernate.PersistentObjectException: detached entity passed to persist: Organisation

Ich weiß, dass ein beharren auf einer frei stehende Einheit nicht aufrufen kann. Aber in diesem Fall, da ich selbst nichts über die Organisation Einheit ändern, dachte ich Hibernate würde es erlauben.

Ich habe versucht, cascade = {CascadeType.Persist, CascadeType.Merge} in die ManyToOne Annotation, aber das endet in dem gleichen Fehler.

Ist das, was ich mit Hibernate nicht möglich archivieren möchten, oder muss ich irgendwo einen Denkfehler haben?

+0

Mögliche doppelte von [JPA/Hibernate: freistehende Einheit übergeben beharren] (http://stackoverflow.com/questions/13370221/jpa-hibernate-detached-entity-passed-to-persist) – agilob

+0

Sie müssen Datenbankrelation in eine bessere Art und Weise verwalten, erfahren Sie mehr hier https://stackoverflow.com/questions/13370221/jpa-hibernate-detached-entity-passed-to-persist – agilob

Antwort

1

Sie wurden in der richtigen Richtung mit dem Gehen:

cascade = {CascadeType.Persist, CascadeType.Merge} 

Die Sache ist die, dass, wenn Sie noch save Operation durchführen, die Persistenz-Provider versucht, den persist Betrieb kaskadieren, so dass es die Organisation versucht, endet zu anhalten Entität, für die bereits eine @Id eingerichtet ist und die gelöst ist.

Was Sie tun müssten, ist durchzuführen merge anstelle von save.

In diesem Fall wird das neue Unternehmen beibehalten werden und die Organisation wird wieder in den Persistenzkontext damit verschmolzen werden, die ganze Operation ermöglicht, erfolgreich zu sein.

Denken Sie daran, dass, wenn Sie Druck verwenden möchten Operationen auf dem übergebenen Einheit danach auszuführen, würden Sie brauchen, um das Ergebnis zu einer neuen Variablen zuweisen und führen den Betrieb auf sie fe:

User mergedUser = userRepo.merge(user); 

// operations on mergedUser from now on 
+0

Hallo, vielen dank für die schnelle Antwort! :) Da ich Spring Framework und die JpaRepository-Klasse verwende, habe ich dort keine Merge-Methode. Bedeutet das, dass ich eine interne Hibernate-Repository-Klasse verwenden muss? Wie der EntityManager? Oder vielleicht, wenn Spring Repos auch eine Merge-Funktion bietet. Ich blätterte schnell durch die Dokumente, fand aber nichts. – SakeSushiBig

+0

Und kann ich anrufen, auch auf eine neue Einheit verschmelzen? – SakeSushiBig

+0

Ja, es wird die Erstellung einer neuen Entität unterstützen. Sie müssen jedoch daran denken, dass die Zusammenführung ein wenig teurer ist als das Weiterbestehen. Sie können erwägen, die Zusammenführung für die Organisation durchzuführen und dann für den Benutzer beizubehalten. Wenn es dir egal ist und du alles auf einmal machen willst, dann folge meiner Antwort. –