2011-12-23 9 views
12

Ho una domanda simile a @ManyToMany without join table (legacy database) con un ulteriore problema.Mapping di un database di sola lettura con una relazione molti-a-molti senza una tabella di join

ho due tabelle A e B

  • A con una chiave multipla colonna primaria (ID e ID2)
  • B con una chiave multipla colonna primaria (ID e ID3)

Una riga in A può fare riferimento a più righe in B (B.ID = A.ID) e una riga in B può essere referenziata da più righe in A.

EDIT: il database è un database legacy di sola lettura che non posso modificare. Non ho bisogno di mappare le relazioni con JPA (potrei farlo nella logica del mio programma con selezioni aggiuntive) ma sarebbe bello.

È fondamentalmente una relazione molti-a-molti senza una tabella di join. Dato che, come per la domanda collegata, devo solo leggere le tabelle, ho provato con due relazioni uno-a-molti in entrambe le classi.

Il problema aggiuntivo che ho è che entrambi i ID s utilizzati per il join non sono la chiave primaria.

ho le seguenti classi:

@Entity 
@Table(name = "A") 
@IdClass(PrimaryKeysA.class) 
public class A { 

    @Id 
    @Column(name = "ID", insertable = false, updatable = false, columnDefinition = "char") 
    private String id; 

    @Id 
    @Column(name = "ID2", insertable = false, updatable = false) 
    private int id2; 

    @OneToMany(cascade = CascadeType.ALL) 
    @JoinColumn(name = "ID", columnDefinition = "char", referencedColumnName = "ID") 
    private Set<B> setOfBs; 

} 

@Entity 
@Table(name = "B") 
@IdClass(PrimaryKeysB.class) 
public class B { 

    @Id 
    @Column(name = "ID", insertable = false, updatable = false, columnDefinition = "char") 
    private String id; 

    @Id 
    @Column(name = "ID3", insertable = false, updatable = false) 
    private int id3; 

    @OneToMany(cascade = CascadeType.ALL) 
    @JoinColumn(name = "ID", columnDefinition = "char", referencedColumnName = "ID") 
    private Set<A> setOfAs; 

} 

Hibernate genera il seguente errore:

Exception while preparing the app : referencedColumnNames(ID) of package.B referencing package.A not mapped to a single property 

Io davvero non capisco il messaggio: B.id fa riferimento a un singolo immobile in A (A.id) .

EDIT: come richiesto:

public class PrimaryKeysA implements Serializable { 

private static final long serialVersionUID = 1L; 

private int id1; 
private int id2; 

    // getters/setters/equals/hashcode 

} 

PrimaryKeysB è simile con ID3 invece di ID2. Entrambe le classi A e B sono esempi semplificati (resi anonimi).

+1

Non vedo davvero come si possa avere un numero molti con queste tabelle. Riferimenti A.ID B.ID e B.ID è la chiave primaria di B. Quindi una data A può fare riferimento solo a una B. Hai solo un'associazione ManyToOne da A a B. –

+0

Ooops mi dispiace ho lo stesso su A come in B. Io modifico la domanda (ho provato a generare un esempio semplificato andando troppo lontano) – Matteo

+0

Questa non è un'associazione molti a molti tra due tabelle ... Perché stai usando due ID su ogni tabella? Avete la possibilità di cambiare questo schema in un modulo più standard o si tratta di un database legacy? Se non si tratta di un database precedente, qual è la ragione per cui non si utilizza una tabella di join se si desidera un'associazione many-to-many? –

risposta

4

Si potrebbe creare una vista che avrebbe agito come aderire a tavola:

CREATE VIEW AJOINB AS 
SELECT A.ID as AID, A.ID2 as AID2, B.ID as BID, B.ID3 as BID3 
FROM A JOIN B ON A.ID = B.ID 

E poi la mappa in JPA come ManyToMany con AJOINB come unirsi a tavola.

Se A.ID2 e B.ID3 erano unici da soli, non sarebbe nemmeno necessario mappare A.ID e B.ID nei bean JPA.

+0

Poiché il DB è di sola lettura, dovrei creare un nuovo DB con una copia di tutte le tabelle più la vista aggiuntiva (poiché non pensare che potrei definire due entità su un DB e la tabella di join su un'altra). Dovendo utilizzare un DB aggiuntivo, proverei quindi a rifattorizzare i dati in un modo migliore. Ma potrebbe valere ... – Matteo

+0

Dipende dal tuo DB. In Oracle e SQL Server è possibile utilizzare alias di tabella. E creare una vista attraverso gli schemi è possibile anche in MySQL. – greyfairer

+0

Sì, la creazione della vista in un altro schema non è un problema. Temo (non ho verificato) che la definizione di un'entità in uno schema con la tabella di join in un'altra non funzioni. Ma dovrò lavorare con un collegamento DB poiché il DB (non solo lo schema) è di sola lettura: non ho altri accessi. – Matteo

2

Puoi condividere alcuni record di esempio dalle tue tabelle?

Il problema è molto chiaro. Per qualsiasi relazione uno-molti, sul lato "uno", dovrebbe esserci solo un record che può essere identificato in modo univoco. Qui, penso, dal momento che id non è univoco ci sono più voci.

Si può provare a utilizzare @JoinColumns e aggiungere entrambe le colonne per identificare in modo univoco l'entità sul lato "uno".

@OneToMany 
@JoinColumns({ 
    @JoinColumn(name="yourID1", referencedColumnName="yourID1"), 
    @JoinColumn(name="yourid2", referencedColumnName="yourid2") 
}) 

Suppongo che tu abbia i seguenti dati.

tabella A:

id2 c1   id 
100 content1 1000 
101 content2 1001 

tabella B:

id3 s1   id 
100 content1 1000 
101 content2 1000 
102 content3 1001 
103 content4 1001 

Qui ID2 e ID3 sono unici. A.id è unico ma b.id non lo è; un tipico scenario OneToMany.

Se traccio A a B usando A.id e B.id, allora questo diventa uno-a-molti dove A (100) può riferirsi a B (100, 101) come id è 1000

Questo funzionerà bene penso. Ma se devi mappare da B ad A usando le stesse colonne (come indicato nella domanda) non funzionerà come un lato (B) ha duplicati.

Sono in grado di comprendere correttamente la domanda?

+0

A proposito, non so come aggiungere questo come commento senza pubblicare qualcosa come risposta. Qualcuno può aiutarmi? –

+0

Hibernate si lamenta da tutti i lati. Ho un A.id1 che fa riferimento a B.id1. B.id1 non è univoco (uno-a-molti). Hibernate si lamenta dicendo che B.id1 fa parte di una chiave primaria: ma a chi importa. Per ogni A.id1 ho più B.id1s. Se B.id1 è anche ** parte ** della chiave primaria di B non dovrebbe essere rilevante. Le tabelle sono collegate solo tramite id1 (id2 non esiste in B). – Matteo

+0

Hai bisogno di una reputazione di 50 per poter commentare – Matteo

Problemi correlati