- Learn
- Guida JEE 7, EJB 3 e JPA
- JPA: gestire tabelle con nomi relazionali diversi
JPA: gestire tabelle con nomi relazionali diversi
Cosa fare se volessimo riutilizzare la classe Address
all’interno di diverse Entities in cui le tabelle associate contengono gli stessi campi ma con nomi relazionali diversi? Immaginiamo di avere un Entity Order che contiene gli stessi campi di Address per l’indirizzo di spedizione, ma con nomi sulla tabella ORDER_TABLE
come a STREET_SHIPMENT
, CITY_SHIPMENT
, STATE_SHIPMENT
. Come possiamo utilizzare Address
come classe Embedded nell’Entity Order?
La soluzione fornita da JPA risiede nell’utilizzo dell’annotation @AttributeOverrides
che consente di ridefinire di volta in volta il nome della colonna associata.
@Entity
@Table(name="ORDER_TABLE")
public class Order {
......
private Address address;
......
@Embedded
@AttributeOverrides({
@AttributeOverride(name="street", [email protected](name="STREET_SHIPMENT")),
@AttributeOverride(name="city", [email protected](name="CITY_SHIPMENT")),
@AttributeOverride(name="state", [email protected](name="STATE_SHIPMENT"))
})
public Address getAddress(){
}
.....
}
Abbiamo mostrato come utilizzando l’annotation @Id
sia possibile specificare un campo di un Entity come identificativo dell’Entity stessa. I valori sul tale campo vengono generati automaticamente attraverso l’uso di una di tre possibili strategie:
- Identity generator
- Sequence generator
- Table generator
Tutte queste strategie fanno uso dell’annotation @GeneratedValue
; in tali situazioni un vincolo Identity può essere utilizzato per la generazione dei valori della chiave primaria. Tutto ciò che dobbiamo fare a livello di codice è applicare @GeneratedValue
sul metodo get annotato con @Id
:
@Entity
@Table(name="CUSTOMER_TABLE")
public class Customer{
....
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="CUSTOMER_ID")
public long getId(){....}
....
}
Il codice assume che un vincolo Identity sia definito sulla colonna CUSTOMER_ID
in CUSTOMER_TABLE
. Il valore sul campo chiave dell’Entity sarà disponibile dopo l’operazione di persistenza che salva un’istanza dell’Entity sul database.
Per utilizzare un Sequence Generator, dobbiamo per prima cosa definire una sequence a livello di database da collegare al campo chiave dell’Entity. Costruiremo ed eseguiremo preliminarmente un’istruzione SQL del tipo:
CREATE SEQUENCE CUSTOMER_SEQUENCE START WITH 1 INCREMENT BY 10;
Successivamente definiamo il Sequence Generator a livello di Entity utilizzando @SequenceGenerator
e
specifichiamo l’uso del sequence generator con l’attributo generator di @GeneratedValue
che punta
al nome del generatore
@Entity
@Table(name="CUSTOMER_TABLE")
@SequenceGenerator(name="CUSTOMER_SEQUENCE_GEN",sequenceName="CUSTOMER_SEQUENCE")
public class Customer {
....
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE,generator="CUSTOMER_SEQUENCE_GEN")
@Column(name="CUSTOMER_ID")
public long getId(){..}
....
}
Esaminiamo ora la strategia Table Generator. In questa caso si utilizza una tabella che memorizza nomi di sequence e valori associati:
CREATE TABLE SEQUENCE_TABLE (
SEQUENCE_NAME VARCHAR NOT NULL,
SEQUENCE_VALUE NUMBER NOT NULL,
PRIMARY KEY (SEQUENCE_NAME)
)
Il passo successivo è quello di inserire un’entry per il campo chiave id
dell’Entity Customer:
INSERT INTO SEQUENCE_TABLE(SEQUENCE_NAME,SEQUENCE_VALUE) VALUES('CUSTOMER_SEQUENCE',1)
Possiamo vedere questi due step come equivalenti al singolo step del Sequence Generator. Anche se la strategia Table Generator è più complessa ha il vantaggio che la stessa Sequence Table ospita una molteplicità di sequence fornendo un controllo centralizzato sulla generazione delle chiavi primarie. A livello di codice l’uso di un Table generator è molto simile ad un Sequence Generator:
@Entity
@Table(name="CUSTOMER_TABLE")
@TableGenerator(name="TABLE_GENERATOR",
table="SEQUENCE_TABLE",
pkColumnName="SEQUENCE_NAME",
valueColumnName="SEQUENCE_VALUE",
pkColumnValue="CUSTOMER_SEQUENCE")
public class Customer {
....
@Id
@GeneratedValue(strategy=GenerationType.TABLE,generator="TABLE_GENERATOR")
@Column(name="CUSTOMER_ID")
public long getId(){..}
....
}
Come possiamo notare l’annotation @TableGenerator
consente di specificare il nome della tabella generatrice,
i nomi delle colonne e la particolare sequence che intendiamo usare (attributo pkColumnValue
) a livello di Entity sul campo annotato con @Id
.
Se vuoi aggiornamenti su Java inserisci la tua email nel box qui sotto:
Compilando il presente form acconsento a ricevere le informazioni relative ai servizi di cui alla presente pagina ai sensi dell'informativa sulla privacy.
La tua iscrizione è andata a buon fine. Se vuoi ricevere informazioni personalizzate compila anche i seguenti campi opzionali:
Compilando il presente form acconsento a ricevere le informazioni relative ai servizi di cui alla presente pagina ai sensi dell'informativa sulla privacy.
I Video di HTML.it
Droidcon Italy 2017, un altro successo di Synesthesia
Synesthesia è l’azienda che ormai da quattro anni si fa propulsore e promotore di Droidcon, un evento dal respiro internazionale, […]