Una relazione ManyToOne
in Java è quella in cui l’oggetto sorgente ha un attributo che fa riferimento a un altro oggetto, l’oggetto destinazione. Cioè il caso piuttosto tipico di Java in cui un oggetto detiene un riferimento ad un altro oggetto. Una relazione ManyToOne
può essere specificata unidirezionale. Tuttavia, è tipico che l’oggetto di destinazione abbia la relazione inversa specificata all’oggetto sorgente. Questa sarebbe una specificazione di relazione OneToMany
nell’oggetto di destinazione. Tutte le relazioni in Java e JPA sono unidirezionali, nel senso che se un oggetto sorgente fa riferimento ad un oggetto destinazione non c’è garanzia che l’oggetto destinazione abbia anche una relazione con l’oggetto sorgente. Questo è diverso da un database relazionale, in cui le relazioni sono definite attraverso chiavi esterne e interrogazioni tali che la query inversa esiste sempre.
In JPA una relazione ManyToOne
è specificata attraverso l’annotazione @ManyToOne
o l’elemento <many-to-one>
. Un’annotazione @ManyToOne
è tipicamente accompagnata da un’annotazione @JoinColumn
. L’annotazione @JoinColumn
specifica come la relazione dovrebbe essere mappata in (espressa in) un database. Il @JoinColumn
definisce il nome della colonna chiave esterna (@JoinColumn(name = "...")
) nell’oggetto sorgente che dovrebbe essere usata per trovare (unirsi) all’oggetto destinazione.
Se la relazione inversa OneToMany
è specificata nell’oggetto destinazione, allora l’annotazione @OneToMany
nell’oggetto destinazione deve contenere un attributo mappedBy
per definire questa relazione inversa.
JPA definisce anche una relazione OneToOne
, che è simile a una relazione ManyToOne
, tranne che la relazione inversa (se fosse definita) è una relazione OneToOne
. La differenza principale tra una relazione OneToOne
e una ManyToOne
in JPA è che una ManyToOne
contiene sempre una chiave esterna dalla tabella dell’oggetto sorgente alla tabella dell’oggetto destinazione, mentre in una relazione OneToOne
la chiave esterna può essere sia nella tabella dell’oggetto sorgente che nella tabella dell’oggetto destinazione.
- Esempio di una relazione ManyToOne databaseEdit
- Esempio di relazione ManyToOne annotazioniEdit
- Esempio di relazione ManyToOne relazione XMLEdit
- Vedi ancheEdit
- Problemi comuniModifica
- La chiave esterna è anche parte della chiave primaria.Modifica
- La chiave esterna è anche mappata come una chiave base.Edit
- Errore di vincolo su insert.Edit
- Il valore della chiave esterna è nullEdit
Esempio di una relazione ManyToOne databaseEdit
EMPLOYEE (tabella)
EMP_ID | FIRSTNAME | LASTNAME | SALARY | MANAGER_ID |
1 | Bob | Way | 50000 | 2 |
2 | Sarah | Smith | 75000 | null |
PHONE (tabella)
ID | TYPE | AREA_CODE | P_NUMBER | OWNER_ID |
1 | home | 613 | 792-0000 | 1 |
2 | lavoro | 613 | 896-1234 | 1 |
3 | lavoro | 416 | 123-4444 | 2 |
Esempio di relazione ManyToOne annotazioniEdit
@Entitypublic class Phone { @Id private long id; ... // Specifies the PHONE table does not contain an owner column, but // an OWNER_ID column with a foreign key. And creates a join to // lazily fetch the owner @ManyToOne(fetch=FetchType.LAZY) @JoinColumn(name="OWNER_ID") private Employee owner; ...}// Specification of the reverse OneToMany relationship in Employee@Entitypublic class Employee { @Id private long emp_id; ... // The 'mappedBy = "owner"' attribute specifies that // the 'private Employee owner;' field in Phone owns the // relationship (i.e. contains the foreign key for the query to // find all phones for an employee.) @OneToMany(mappedBy = "owner") private List<Phone> phones; ...
Esempio di relazione ManyToOne relazione XMLEdit
<entity name="Phone" class="org.acme.Phone" access="FIELD"> <attributes> <id name="id"/> <many-to-one name="owner" fetch="LAZY"> <join-column name="OWNER_ID"/> </many-to-one> </attributes></entity>
Vedi ancheEdit
- Relazioni
- Cascading
- Lazy Fetching
- Target Entity
- Join Fetching
- Lettura in blocco
- Problemi comuni
- OneToOne
- Mappare una OneToOne utilizzando una tabella di unione
- OneToMany
Problemi comuniModifica
La chiave esterna è anche parte della chiave primaria.Modifica
Vedi Chiavi primarie attraverso relazioni OneToOne.
La chiave esterna è anche mappata come una chiave base.Edit
Se usi lo stesso campo in due mappature diverse, in genere devi rendere una di esse di sola lettura usando insertable, updatable = false
. Vedere Target Foreign Keys, Colonne di unione della chiave primaria, Chiavi primarie a cascata.
Errore di vincolo su insert.Edit
Questo tipicamente si verifica perché hai mappato in modo errato la chiave esterna in una relazione OneToOne
. Vedi Target Foreign Keys, Primary Key Join Columns, Cascade Primary Keys. Può anche verificarsi se il vostro provider JPA non supporta l’integrità referenziale o non risolve i vincoli bidirezionali. In questo caso potrebbe essere necessario rimuovere il vincolo, o usare EntityManager
flush()
per assicurare l’ordine in cui i tuoi oggetti sono scritti.
Il valore della chiave esterna è nullEdit
Assicurati di impostare il valore del OneToOne
dell’oggetto, se il OneToOne
fa parte di una relazione bidirezionale OneToMany
, assicurati di impostare il OneToOne
dell’oggetto quando aggiungi un oggetto al OneToMany
, JPA non mantiene le relazioni bidirezionali per te. Controllate anche di aver definito correttamente il JoinColumn
, assicuratevi di non aver impostato insertable, updateable = false
o usato un PrimaryKeyJoinColumn
.