6


devo lavorare con Hibernate e io non sono molto sicuro di come risolvere questo problema, ho 2 tabelle con una relazione 1..n come questo:
Hibernate chiave esterna con una parte della chiave primaria composita

 
------- 
TABLE_A 
------- 
col_b (pk) 
col_c (pk) 
[other fields] 

------- 
TABLE_B 
------- 
col_a (pk) 
col_b (pk) (fk TABLE_A.col_b) 
col_c (fk TABLE_A.col_c) 
[other fields] 

Come posso gestirlo con Hibernate?

Non ho idea di come dichiarare una chiave esterna che conterrebbe una parte della chiave primaria.

Lo schema del mio database è generato dal modello Hibernate.

+1

Se si desidera combattere l'ibernazione ... andare avanti e utilizzare i tasti compositi. Se vuoi una vita molto più semplice, assicurati che ogni tabella abbia una singola colonna di chiave primaria. Fidati di me, non vale la pena combattere ... è una battaglia che ti costerà molte ore in futuro –

+0

Cosa intendi per "parte della chiave primaria"? Le chiavi primarie composite in Hibernate sono abbastanza semplici, ma non dovresti cercare di complicarla cercando di usarne solo una parte. In generale è necessario un codice categoria composito. C'è una risposta qui con tutti i dettagli di base: http://stackoverflow.com/questions/3585034/how-to-map-a-composite-key-with-hibernate – Karolis

+0

C'è una risposta abbastanza approfondita qui: http: // StackOverflow .com/a/3588400/3166303 – leeor

risposta

5

Ho trovato due soluzioni a questo problema.

Il primo è piuttosto una soluzione alternativa e non è così semplice come il secondo.

definire la chiave principale del soggetto B come chiave composta contenente col_a, col_b e col_c e quello che doveva essere la chiave primaria, in primo luogo, definire vincolo come unica. Lo svantaggio è che la colonna col_c non è concettualmente parte della chiave primaria.

@Entity 
class A { 
    @Id 
    private int b; 
    @Id 
    private int c; 
} 

@Entity 
@Table(uniqueConstraints = {@UniqueConstraint(columnNames = { "a", "b" }) }) 
class B { 
    @Id 
    private int a; 

    @Id 
    @ManyToOne(optional = false) 
    @JoinColumns(value = { 
      @JoinColumn(name = "b", referencedColumnName = "b"), 
      @JoinColumn(name = "c", referencedColumnName = "c") }) 
    private A entityA; 
} 

il secondo utilizza @EmbeddedId e @MapsId annotazioni e fa esattamente quello che volevo essere fatto proprio all'inizio.

@Entity 
class A { 
    @Id 
    private int b; 
    @Id 
    private int c; 
} 

@Embeddable 
class BKey { 
    private int a; 
    private int b; 
} 

@Entity 
class B { 
    @EmbeddedId 
    private BKey primaryKey; 

    @MapsId("b") 
    @ManyToOne(optional = false) 
    @JoinColumns(value = { 
      @JoinColumn(name = "b", referencedColumnName = "b"), 
      @JoinColumn(name = "c", referencedColumnName = "c") }) 
    private A entityA; 
} 
0

seconda soluzione di Jagger che è la mia prima reazione, con @EmbededId e @MapsId. Quanto segue è un altro modo basato sulla sua seconda soluzione ma senza usare @MapsId.

@Entity 
class A { 
    @Id 
    private int b; 
    @Id 
    private int c; 
} 

@Embeddable 
class BKey { 
    private int a; 
    private int b; 
} 

@Entity 
class B { 
    @EmbeddedId 
    private BKey primaryKey; 

    @ManyToOne(optional = false) 
    @JoinColumns(value = { 
      @JoinColumn(name = "b", referencedColumnName = "b", insertable= false, updatable= false), 
      @JoinColumn(name = "c", referencedColumnName = "c") },) 
    private A entityA; 
} 
+0

Questo non funzionerà e termina con un'eccezione 'org.hibernate.AnnotationException: non è consentito mescolare colonne inseribili e non inseribili in una proprietà' C'è un Hibernate [bug] (https://hibernate.atlassian.net/browse/HHH-6221) per questo. – Jagger