2012-06-09 2 views
14

Ich habe zwei Klassen Foo und Bar. Die Tabellen in der Datenbank wie folgt aussehen:Composite-Primärschlüssel, Fremdschlüssel. Referenz auf Objekt oder Schlüssel?

|Foo| 
|id : INT (PK) | bar_id : INT (PK, FK) | 

|Bar| 
|id : INT (PK) | 

Normalerweise würde ich es wie diese Karte:

@Entity 
public class Bar 
{ 
    @Id 
    @Column(name = "id") 
    private int id; 

    @OneToMany 
    private Set<Foo> foo; 
} 

@Entity 
public class Foo 
{ 
    @EmbeddedId 
    private FooPK key; 

    @MapsId("barId") 
    @ManyToOne 
    @JoinColumn(name = "bar_id", referencedColumnName = "id") 
    private Bar bar; 
} 

@Embeddable 
public class FooPK 
{ 
    @Column(name = "id") 
    private int id; 
    @Column(name = "bar_id") 
    private int barId; 
} 

jedoch die IDs in FooPK werden müssen lose kartiert und manuell verbunden werden. Ich würde eine Lösung bevorzugen, die Objekte anstelle von losen IDs mit Objekten abbildet. Ich habe versucht, die folgenden aber (natürlich) es hat nicht funktioniert, aber ich denke, es ist eine Vorstellung davon, was Ich mag erreichen würde:

@Entity 
public class Bar 
{ 
    @Id 
    @Column(name = "id") 
    private int id; 

    @OneToMany 
    private Set<Foo> foo; 
} 

@Entity 
public class Foo 
{ 
    @EmbeddedId 
    private FooPK key; 

    @MapsId("barId") 
    @ManyToOne 
    @JoinColumn(name = "bar_id", referencedColumnName = "id") 
    @Access(AccessType.FIELD) 
    private Bar getBar() 
    { 
     return key.getBar(); 
    } 
} 

@Embeddable 
public class FooPK 
{ 
    @Column(name = "id") 
    private int id; 

    @Transient 
    private Bar bar; 

    //.... 

    @Column(name = "bar_id") 
    @Access(AccessType.PROPERTY) 
    private int getBarId 
    { 
     return bar.getId(); 
    } 
} 

Ein weiteres Problem mit dieser Lösung ist, dass die getBarId() Verfahren in FooPK muss eine setBarId(Int) Methode haben. Das Festlegen des Objekts mit der ID kann durch Zugriff auf die Datenzugriffsebene erfolgen, was jedoch (meiner Meinung nach) die Trennung von Geschäfts-/Domänen-/Datenschichten verletzt.

Was also zu tun? Gehen Sie mit der ersten Lösung und halten Sie die IDs manuell synchronisiert oder gibt es eine andere (beste) Praxis?

Antwort

23

zur JPA 2: composite primary key classes Diskussion Bezug genommen, die folgenden Änderungen an den Foo und FooPK Klassen:

@Entity 
public class Foo { 

    @EmbeddedId 
    private FooPK key; 

    @MapsId("barId") //references EmbeddedId's property 
    @JoinColumn(name = "bar_id", referencedColumnName = "id") 
    @ManyToOne 
    private Bar bar; 
} 

@Embeddable 
public class FooPK { 

    @Column(name = "id") 
    private int id; 
    @Column(name = "bar_id") 
    private int barId; 
} 

ich zum ersten Mal schlage vor, dass es mit FIELD Zugang zu arbeiten und dann PROPERTY Zugang beantragen.

Was also zu tun? Gehen Sie mit der ersten Lösung und halten Sie die IDs synchron manuell oder gibt es eine andere (beste) Praxis?

Sparen Sie sich vor Schmerzen - generieren Sie automatisch IDs.

+0

Das ist also das erste Beispiel. Ich habe gesehen, dass dies der "Weg zu gehen" ist. Ich habe mich nur gefragt, ob das zweite Beispiel ein sauberer Weg war. Ich denke, das ist dann ein Nein? – siebz0r

+0

@ siebz0r oh, sorry, habe nicht bemerkt das erste Beispiel war das gleiche; o. Ich denke, dass es einfacher ist, PK zu betrachten, wenn es IDs, nicht gemappte Objekte gibt. Wenn Sie nach FooPK suchen, benötigen Sie nur ganze Zahlen und keine Objekte mit allen unnötigen Eigenschaften. – JMelnik

Verwandte Themen