2016-07-29 7 views
1

Ich baue eine Anwendung mit Hibernate. Ich arbeite mit einem Datenbankschema, das (unter anderem) zwei Tabellen assignment und assignment_type enthält. Letzteres enthält Primärschlüssel/Wert-Paare, die den Typ des assignment beschreiben (z. B. "geschrieben", "praktisch").Hibernate: Setzen Sie eine Eins-zu-viele-Referenz eines neuen Datenbankobjekts auf ein anderes Objekt, ohne zuerst das vorhandene Objekt zu erstellen

assignment ist jedoch eine abstrakte Klasse um Klassen wie written_assignment und practical_assignment erweitert. Dazu verwende ich die Klassentabelle Vererbung Ansatz (some details on the topic).

Nun wäre es sinnvoll, einen Verweis auf das entsprechende Objekt zu setzen in den assignment_type bei der Erstellung von Instanzen von Klassen wie written_assignment, etwa wie folgt:

public WrittenAssignment() { 
    AssignmentType assignmentType = ...; // Create or acquire appropriate instance 
    this.setAssignmentType(assignmentType); 
} 

Soweit ich es verstehe, gehe mit dem "create instance" -Ansatz wird nur einmal funktionieren, das eine Mal ist der Zustand, wenn noch kein Objekt in der Datenbank mit diesem Wert ist (da der Wert der assignment_type Tabelle eindeutig festgelegt ist).

Gibt es eine Möglichkeit, einen Verweis auf ein Objekt von assignment_type im Konstruktor WrittenAssignment zu setzen, ohne es zuerst zu erwerben? Bonusfrage: Kann es erstellt werden, wenn noch kein passendes Objekt existiert?

Antwort

1

Sie können die Spalte verwenden, die die assignment_type Tabelle aus der assignment Tabelle als Diskriminator Spalte verweist, und dann ordnen Sie die AssignmentType Beziehung als nur lesen @ManyToOne, Einstellung insertable und updatable-false.

@Entity 
@Inheritance(strategy=InheritanceType.JOINED) 
@DiscriminatorColumn(name="ASSIGNMENT_TYPE_ID") 
@Table(name="assignment") 
public abstract class Assignment { 
    ... 
    @ManyToOne 
    @JoinColumn(name = "ASSIGNMENT_TYPE_ID", insertable = false, updatable = false) 
    private AssignmentType assignmentType; 
} 

In der Kind-Klasse, legten Sie den sachgemäßen Scheider Spaltenwert mit der @DiscriminatorValue Anmerkung:

@Entity 
@DiscriminatorValue("W") 
@Table(name="written_assignment") 
public class WrittenAssignment extends Assignment { 
    ... 
} 

Wenn Sie eine neue Kind-Einheit erstellen müssen, verwenden Sie den Konstruktor und den Zuweisungstyp implizit wären aufgrund des Kind-Entity-Diskriminators. Wenn Sie eine vorhandene Entitätsinstanz lesen und den zugehörigen Zuordnungstyp abrufen, wird der entsprechende Zuordnungstyp geladen.

+0

Danke, das funktioniert wie ein Charme! Gibt es eine Chance, dass der Diskriminator verwendet werden kann, um automatisch die entsprechende Kindklasse zu holen, wenn es sich um eine Abfrage der Superklasse handelt? – koala

+1

Versuchen Sie, eine Abfrage von Zuweisungseinheiten auszuführen. Die zurückgegebene reale Klasse der Ergebnisinstanzen muss vom konkreten Typ sein (nicht vom übergeordneten abstrakten Typ). – JMSilla

+0

Danke nochmal! Das wäre das Verhalten, das ich erwarten würde, und es funktioniert teilweise. Ich habe die toString-Methoden optimiert, damit sie die echte Klasse identifizieren, die funktioniert. Ich kann jedoch nicht mit 'instanceof' nach der untergeordneten Klasse suchen, noch kann ich sie typisieren. 'getClass(). getName()' gibt den Namen der abstrakten Klasse zurück, gefolgt von einer Reihe von Unterstrichen, Dollarzeichen und anderen Zeichen. Ich nehme an, dass das etwas mit Reflexionen zu tun hat, die ich nicht verstehe. – koala