2014-06-10 12 views
6

Ich bin auf die verschiedenen Möglichkeiten der Annotation Karten mit Hibernate 4.1.9 & JPA-Annotationen.Key & Wert Spaltenname überschreibt beim Mapping java.util.Map mit JPA-Annotationen

Wenn ich eine Karte gespeichert werden soll, wo der Schlüssel ein Attribut des Entity-Wert ist die Marke nach oben wie folgt aussieht

@OneToMany(mappedBy = "deptById", targetEntity = com.demo.impls.Employee.class) 
    @MapKey(name = "entityId") 
    private Map<Long, Employee> employeesById; 

Beachten Sie die oben Auszeichnungs nicht schaffen eine Tabelle beitreten, aber die Karte zurückgegeben über eine Abfrage zur Laufzeit, so dass die Map dynamisch ist und Sie kein Element in die Map in Java einfügen müssen, damit sie von der Abfrage zurückgegeben werden.

Jetzt möchte ich den Inhalt der Map widerspiegeln, was die Anwendung in die Map hinzugefügt hat, anstatt eine dynamische Abfrage durchzuführen.

Es gibt 4 Sorten von Karte I

private Map<String, String> map0; 
    private Map<String, Entity> map1; 
    private Map<Entity, String> map2; 
    private Map<Entity, Entity> map3; 

In diesen Fällen gibt es keine Beziehung zwischen dem Schlüssel & und Wert speichern wollen, noch ist es eine Beziehung zu dem Halt Entity. Ich muss in der Lage sein, den Namen der Join-Tabelle sowie die Spaltennamen für den Schlüssel & Wert anzugeben.

Ich habe das versucht folgende

@Entity 
public class Department { 
    @ElementCollection 
    @CollectionTable(name = "TEST_MAP0") 
    @Column(name="value") 
    @MapKeyColumn(name="Key") 
    private Map<String, String> map0; 

    @ElementCollection(targetClass = com.demo.bb.impls.Employee.class) 
    @CollectionTable(name = "TEST_MAP1") 
    @Column(name="value") 
    @MapKeyColumn(name="Key") 
    private Map<String, Employee> map1; 

    @ElementCollection 
    @MapKeyClass(value = com.demo.bb.impls.Employee.class) 
    @CollectionTable(name = "TEST_MAP2") 
    @Column(name="value") 
    @MapKeyColumn(name="Key") 
    private Map<Employee, String> map2; 

    @ElementCollection(targetClass = com.demo.bb.impls.ParkingSpace.class) 
    @MapKeyClass(value = com.demo.bb.impls.Employee.class) 
    @CollectionTable(name = "TEST_MAP3") 
    @Column(name="value") 
    @MapKeyColumn(name="Key") 
    private Map<Employee, ParkingSpace> map3; 

Fall 0 Karte funktioniert & die Tabelle Spalten DEPARTMENT verbinden erzeugt, WERT, KEY

Die anderen drei Fälle in so viel arbeiten, wie Sie Daten speichern können in den Tabellen & in Java die Tabellen mit den relevanten Schlüsseln/Werten abfragen & erhalten Sie die erwarteten Ergebnisse zurück - dh behandelt es die Speicherung von Entitäten mit @ElementCollection

Der Spaltenname überschreibt jedoch @Column (Name = "Wert") & @MapKeyColumn (Name = "Schlüssel") werden ignoriert, wenn der Schlüssel oder Wert eine Entität ist.

Ich habe versucht, Anmerkungen mit @ManyToMany als

@ManyToMany(targetEntity = com.demo.bb.impls.Employee.class) 
    @JoinTable(name = "TEST_MAP1_B") 
    @Column(name="value") 
    @MapKeyColumn(name="Key") 
    private Map<String, Employee> map1_B; 

    @ManyToMany(targetEntity = com.demo.bb.impls.ParkingSpace.class) 
    @MapKeyClass(value = com.demo.bb.impls.Employee.class) 
    @JoinTable(name = "TEST_MAP3_B") 
    @Column(name="value") 
    @MapKeyColumn(name="Key") 
    private Map<Employee, ParkingSpace> map3_B; 

folgt aber wieder die Schlüssel & Wert Spaltennamen überschreibt, werden ignoriert. Kennt jemand eine Möglichkeit, diese Überschreibungen für Spaltennamen zu erzwingen?

Vielen Dank im Voraus ...

UPDATE .... Nachdem in der Antwort von @wypieprz suchte Ich denke, ich die richtige Anmerkung wissen, damit Sie Spaltennamen für den Wert & den Schlüssel geben, wenn die Karte wird von einem Basic mit einem Entity-Wert angegeben.

Durch die Verwendung der folgenden

@ManyToMany(targetEntity = com.demo.bb.impls.Employee.class) 
    @JoinTable(name = "TEST_MAP1", [email protected](name="VALUE")) 
    @MapKeyColumn(name="KEY") 
    private Map<String, Employee> map1; 

die inverseJoinColumn Verwendung von I den Wert Spaltennamen angeben.

Aber wenn der Schlüssel eine Entität ist, habe ich keine Möglichkeit gefunden, den Schlüsselspaltennamen anzugeben.Wie das Dokument sagt, @MapKeyColumn "gibt die Zuordnung für die Schlüsselspalte einer Karte, deren Kartenschlüssel ein Basistyp ist"

Ich bin auch nicht sicher, die Anmerkungen zu verwenden, wenn der Schlüssel eine Entität & der Wert ist ein Basic. Die Verwendung von ManyToMany funktioniert einfach nicht. & Ich denke, ich muss möglicherweise die ElementCollection verwenden, aber ich finde keine Möglichkeit, den Schlüsselspaltennamen anzugeben.

UPDATE 2 ... Danke an Peter Halicky für eine Lösung.

Zusammenfassend, um alle 3 Spalten in jedem der Fälle zu benennen, die Sie so etwas tun müssen.

@ElementCollection 
@CollectionTable(name = "TEST_MAP0", joinColumns = @JoinColumn(name = "DEPARTMENT")) 
@Column(name = "value") 
@MapKeyColumn(name = "key") 
private Map<String, String> map0; 

@ManyToMany(targetEntity = com.hibernate.elephants.Employee.class) 
@JoinTable(name = "TEST_MAP1", joinColumns = @JoinColumn(name = "DEPARTMENT"), inverseJoinColumns = @JoinColumn(name = "value")) 
@MapKeyColumn(name = "key") 
private Map<String, Employee> map1; 

@ElementCollection 
@CollectionTable(name = "TEST_MAP2", joinColumns = @JoinColumn(name = "DEPARTMENT")) 
@MapKeyClass(value = com.hibernate.elephants.Employee.class) 
@MapKeyJoinColumn(name = "key") 
@Column(name = "value") 
private Map<Employee, String> map2; 

@ManyToMany(targetEntity = com.hibernate.elephants.ParkingSpace.class) 
@JoinTable(name = "TEST_MAP3", joinColumns = @JoinColumn(name = "DEPARTMENT"), inverseJoinColumns = @JoinColumn(name = "value")) 
@MapKeyClass(value = com.hibernate.elephants.Employee.class) 
@MapKeyJoinColumn(name="key") 
private Map<Employee, com.hibernate.elephants.ParkingSpace> map3; 

Hinweis zwei Fälle werden als ElementCollection spezifiziert, aber die zwei Fälle, in denen der Wert eine andere Entität ist, müssen ManyToMany verwenden.

+0

'@ ElementCollection' und' @ CollectionTable' sollte nur für die Grundtypen und Embeddables verwendet werden, für Unternehmen 'verwenden @ OneToMany' oder' @ ManyToMany'. Hinweis: Sie brauchen '@ MapKeyClass' und' targetEntity' nicht für typisierte java.util.Map – wypieprz

+0

Ich verwende @MapKeyClass, weil die typisierte java.util.Map mit einer Schnittstelle für die Entität eingegeben wurde. Sie benötigen die MapKeyClass, um anzugeben, welche Entitätsklasse instanziiert werden soll. – James

+0

Wie ich in der ursprünglichen Frage gesagt habe, habe ich versucht, @ManyToMany zu verwenden, aber es überschreibt immer noch nicht die Spaltennamen, wenn der Schlüssel oder Wert eine Entität ist – James

Antwort

5

Ich verwende eine Entität als Schlüssel für eine Karte, wie unten. Mit der Annotation @MapKeyJoinColumn könnte ich den Namen der Spalte angeben, die der Schlüssel der Map ist. Dies funktionierte für mich bei Hibernate, nicht sicher, was andere JPA-Implementierungen tun werden, aber es ist sicherlich einen Versuch wert.

@ElementCollection 
@CollectionTable(name="breed_descriptions", joinColumns={ @JoinColumn(name="breed") }) 
@Column(name="description") 
@MapKeyJoinColumn(name="language") 
private Map<Language, String> descriptions = new HashMap<>(); 
Verwandte Themen