2012-04-07 3 views
2

Ich habe 2 Entitäten Stecker und Sockel, die Eins-zu-Eins-Zuordnung haben.Wie man Beziehungen modelliert, die 1: 1-Beziehungen mit Hibernate ändern

Jetzt hat der Stecker eine Fremdschlüsselbeziehung zu der Buchse, an die er angeschlossen ist.

Hibernate generiert eine eindeutige Einschränkung für den Fremdschlüssel, um eine Eins-zu-eins-Beteiligung zu gewährleisten.

Ich habe 10 Stecker, die in 10 Buchsen eingesteckt sind.

Nach einiger Zeit kommt ein Update, das das System über die Änderung der Anordnung informiert.

Das Szenario ist plugA, die in SocketA gesteckt wurde, ist jetzt in SocketB eingesteckt und plugB, das in SocketB gesteckt wurde, ist jetzt in socketA eingesteckt.

Beim Ausführen des Updates versucht Hibernate zuerst, die Fremdschlüsselspalte von plugA auf SocketB zu aktualisieren, was zu einer Verletzung der eindeutigen Integritätsbedingung führt. Dies liegt daran, dass die Beziehung zwischen PlugB und SocketB noch nicht geändert wurde.

Was ist der beste Weg, um die Beziehung zu modellieren?

Beachten Sie, dass das gesamte Update als einzelne Transaktion ausgeführt werden muss.

Dies ist der Code

Innen Buchse

@OneToOne(mappedBy="socket") 
public Plug getPlug() 
{ 
    return plug; 
} 

Innen Stecker @OneToOne (optional = false) öffentlichen Sockel getSocket() { return-Buchse; }

+0

Warum machst du es nicht viele zu eins? viele Stecker für eine Steckdose – kommradHomer

Antwort

0

Ich schlage vor, Sie haben entweder 2 Transaktionen wie

first transction : 
set both plug.socket to null 

second transaction: 
set both plug.socket to what you eventually want 

oder

Verwendung many-to-one

+0

@kommradHommer Danke für den Tipp. –

+0

Was Sie beschreiben, ist der Ansatz für mich gerade jetzt. Was passiert jedoch, wenn die zweite Transaktion aufgrund eines Verstoßes fehlschlägt? Gibt es eine Möglichkeit in Hibernate, eine übergeordnete Transaktion zu haben, die mich zurück in den Ausgangszustand bringen kann? –

0

Ich mochte Ihre Frage so musste ich versuchen, es zu lösen. Ich hoffe also, Sie haben es nicht auf eigene Faust heraus noch .. :)

Also, was Sie tun müssen, um so etwas wie dieses:

@Override 
public void swap(Socket s1, Socket s2) { 
    s1 = em.find(Socket.class, s1.getId()); 
    s2 = em.find(Socket.class, s2.getId()); 
    Plug plug1 = s1.getPlug(); 
    Plug plug2 = s2.getPlug(); 
    plug1.setSocket(null); //This is to avoid duplicate key exception 
    plug2.setSocket(null); 
    em.flush(); //Without this the nullifying will just be overwritten by the next change. 
    plug1.setSocket(s2); 
    plug2.setSocket(s1); 

} 

Jetzt mit dieser seine wichtig, dass das Buchsenfeld ist Nullable/optional. Sie müssen also die optional=true entfernen. Aber das lässt Sie ohne eine eindeutige Einschränkung, die zu Inkonsistenzen führen kann als die Beziehung effektiv eine Eins-zu viele wird .. Also, was Sie tun, ist dies:

@OneToOne 
@JoinColumn(nullable=true, unique=true) 
private Socket socket; 

Also das einzige Problem bleibt, ist, dass Sie jetzt erlaubt sind behalte einen Stecker ohne Steckdose. Dies sollte kein großes Problem sein und kann leicht in Ihrem DAO verhindert/validiert werden.

Verwandte Themen