Abbiamo visto come associare un'Entity ad una singola tabella ma JPA non si limita a fornire soltanto mapping uno a uno Entity-Tabella, consente infatti di mappare Entity su più tabelle. Consideriamo ancora l'Entity Customer ma con qualche campo in più relativo all'indirizzo del cliente:
package it.html.model.hotel;
import java.io.Serializable;
import java.lang.String;
import javax.persistence.*;
@Entity
public class Customer implements Serializable {
private long id;
private String firstName;
private String lastName;
private String street;
private String city;
private String state;
..
}
Supponiamo ora che i campi siano suddivisi su due tabelle con un vincolo di foreign key tra chiave primaria ADDRESS_ID
e chiave primaria CUSTOMER_ID
:
CUSTOMER_TABLE ( CUSTOMER_ID, FIRST_NAME , LAST_NAME)
ADDRESS_TABLE (ADDRESS_ID, STREET, CITY, STATE)
Come mappare i campi in modo che appartengano ad una sola Entity ? Il primo step è usare l'annotation @SecondaryTable
a livello di Entity:
@Entity
@Table(name="CUSTOMER_TABLE")
@SecondaryTable(name="ADDRESS_TABLE",
pkJoinColumns={ @PrimaryKeyJoinColumn(name="ADDRESS_ID") }
)
public class Customer implements Serializable {
......
private String street;
private String city;
private String state;
......
@Column(name="STREET",table="ADDRESS_TABLE")
public String getStreet(){..}
@Column(name="CITY",table="ADDRESS_TABLE")
public String getCity(){..}
@Column(name="STATE",table="ADDRESS_TABLE")
public String getState(){..}
}
Con @SecondaryTable
specifichiamo il nome della seconda tabella e della colonna per l'operazione di Join tra le tabelle, nel nostro caso ADDRESS_ID. Il Join è inteso con la chiave primaria della prima tabella, CUSTOMER_TABLE.
Utilizziamo poi l'annotation @Column
sui campi dell'Entity Customer della seconda tabella per legarli ai campi di ADDRESS_TABLE. Nell'esempio il nome della tabella CUSTOMER_TABLE non coincide con il nome dell'Entity associata (Customer), abbiamo quindi fatto uso dell'annotation @Table
rendendo evidente il mapping dell'Entity sulle tabelle.
In alcuni casi è utile raggruppare più campi in una nuova classe senza che essa dia vita ad una nuova Entity, ferma restando l'associazione di tali campi con la tabella dell'Entity. JPA consente questa operazione tramite le annotations @Embedded
ed @Embeddable
. Nel nostro caso vogliamo avere una classe Address, non Entity, che raggruppi i campi street
, city
e state
della classe Customer senza perdere il mapping con le colonne di CUSTOMER_TABLE. Per mostrare come sia possibile definiamo la classe Address sulla quale applichiamo l'annotation @Embeddable
:
@Embeddable
public class Address {
private String street;
private String city;
private String state;
public String getStreet(){..}
public String getCity(){..}
public String getState(){..}
}
All'interno dell'Entity Customer la utilizzeremo nel seguente modo:
private Address address;
@Embedded
public Address getAddress(){
}
I campi all'interno di Address sono trattati come i campi di un'Entity; in poche parole è come dire all'Entity Customer che i campi della classe devono diventare
campi di persistenza e che quindi devono essere considerati campi presenti sulla tabella associata. Lo scenario
appena visto impone un nome fisso ai campi della classe Address: quello di default pari al nome del campo stesso o
quello che specifichiamo con annotation @Column
.