Introduzione all’utilizzo della JPA

Introduzione all’utilizzo della JPA

All’interno della java EE , JPA (java persistence API) è lo standard API che viene utilizzato
per accedere a databases relazionali e permette di gestire il mappaggio tra oggetti java (POJO)
e dati relazionali.
Questi oggetti così creati vengono chiamati entities (entità java).

Solitamente, ma non sempre, una java entity è associata ad una particolare tabella del database,
quindi una singola riga della tabella viene rappresentata da un’istanza della nostra entità java.

Così come le tabelle di un database sono correlata le une alle altre, anche le entità java
possono essere messe in relazione tra loro tramite relazioni come one-to-one, many-to-one o
many-to-many.

Di conseguenza, così come la gestione dei database relazionali usufruisce di un particolare
standand di linguaggio per modellare i dati (SQL) , la gestione delle entità java utilizza
un meccanismo standard per accedere e modellare le istanze delle entità.
Questo meccanismo è il JPQL (Java Persistence Query Language).

Per poter eseguire una query JPQL , all’interno della nostra procedura in java, avremo
bisogno di utilizzare gli appropriati metoci dell’ EntityManager API e della Query API.

Un importante aiuto nella definizione delle entities e delle operazioni e relazioni tra le
entities ci viene dalla annotazioni definite nella libreria j2ee.jar che ci fornisce le API
EJB 3.0 .

Prendendo un semplice esempio di entity :

@Entity
@Table(name="DIPENDENTI")
@NamedQueries({
@NamedQuery(name="getDipendenti", query = "SELECT x FROM Dipendente x order by x.nome"),
@NamedQuery(name="getDipendenteByNome", query = "SELECT x FROM Dipendente x WHERE x.nome = :nomeX")
})
public class Dipendente implements Serializable {

	@Id
	private BigDecimal id_dipendente;

	private String nome;

	private String cognome;

	private String matricola;

	private String settore;

	@Lob
	private byte[] contratto;

	private Timestamp data_assunzione;

	// ....
	// eventuali costruttori e getter /setter
	// ....
}

Tutte le annotazioni presenti sono definite nel package javax.persistence ( j2ee.jar).
In questo esempio la tabella mappata è la tabella DIPENDENTI (@Table) , che presenta un campo id_dipendente numerico che è la chiave
della tabella ( specificato nella nostra antità tramite l’annotazione @Id ) e altri campi di vario tipo tra cui
ho voluto inserire un campo di tipo Byte[] che è specificato tramite l’annotazione @Lob.
Questa annotazione permette di specificare un campo che correlato con un “large object” in databases che supportano
la memorizzazione di large objects (ad esempio database oracle su cui possono essere memorizzati BLOB ,CLOB e NCLOB).
Sono state definite anche 2 semplici query(tramite l’annotazione @NamedQuery) in JPQL che potranno essere invocate
tramite il nome che abbiamo asegnato loro( name =”…”).

Vediamo dei metodi che possiamo utilizzare per interagire con l’entity definita sopra e quindi per interrogare/modificare
la relativa tabella su DataBase.

Iniziamo creando una classe che gestirà le interazioni con la nostra entità e definiamo per prima cosa
il nostro EntityManager ( package javax.persistence ).
L’interfaccia EntityManager ci fornirà i metodi che permetteranno di effettuare le operazioni di recupero, modifica, inserimento
e cancellazione dei dati delle entità ( find,merge,persist e remove).
Queste operazioni avranno effetto anche sulla/e tabella/e che è correlata con la nostra entity.

L’ EntityManager può essere ottenuto direttamente tramite injection (se siamo dentro un EJB – Enterprise Java Bean)
(“nome_persistence_unit” è il nome simbolico della nostra Persitence Unit , che ci permette
di collegarci ad un particolare schema di un particolare DataBase con dei precisi username e password ):

public class GestisciDipendenti
{

	@PersistenceContext(unitName="nome_persistence_unit",type=PersistenceContextType.TRANSACTION)
	EntityManager em;	
}

oppure tramite l’interfaccia EntityManagerFactory

public class GestisciDipendenti
{
	EntityManager em;
	.....
	....

	createEM(String PersistenceUnitName)
	{
		EntityManagerFactory entityManagerFactory = new PersistenceProvider().createEntityManagerFactory(PersistenceUnitName, null);
		em = entityManagerFactory.createEntityManager();
	}
}

Procediamo quindi con alcuni metodi per la gestione dell’entity :

	public void inserimentoRecord(Dipendente nuovoDipendente)
	{
		em.persist(nuovoDipendente);
		em.flush();
		// Con queste 2 semplici istruzioni abbiamo creato un nuovo record all'interno della tabella "DIPENDENTI" del nostro DataBase.
	}

 public Dipendente ricercaRecord(BigDecimal idDipendente)
	{
		Dipendente dipendente = (Dipendente) em.find(Dipendente.class,idDipendente);
		em.refresh(dipendente);
		return dipendente;
		// Abbiamo recuperato, dalla tabella, il record univoco ( perchè lo abbiamo ricercato
		//tramite la sua chiave) relativo al dipendende con id_dipendente = idDipendente
	}

public 	void modificaRecord(BigDecimal idDipendente)
{
	// recuperiamo il record della tabella che ci interessa
	Dipendente dipendente = ricercaRecord(idDipendente);
	// modifichiamo alcuni suoi campi
	dipendente.setNome("Alessandro");
	// effettuiamo la modifica apportando i cambiamenti sul database
	dipendente = em.merge(dipendente);
	em.flush();
	em.clear();
}

public 	void eliminaRecord(BigDecimal idDipendente)
{
	// recuperiamo il record della tabella che ci interessa
	Dipendente dipendente = ricercaRecord(idDipendente);
	// eliminiamo il record
	em.remove(dipendente);
	em.flush();
}

Vediamo adesso come applicare le query generiche e quindi utilizzare l’interfaccia Query API :

public List trovaTuttiDipendenti() {

		List results = new ArrayList();	

		Query query = em.createNamedQuery("getDipendenti");
		//OPPURE 
		// Query query = em.createQuery("SELECT x FROM Dipendente x ORDER BY x.nome");

		results = (List) query.getResultList();

		return results;
	}

public List trovaDipendetiByNome(String nomeDaCercare) {

		List results = new ArrayList();	

		Query query = em.createNamedQuery("getDipendenteByNome");
		//OPPURE 
		// Query query = em.createQuery("SELECT x FROM Dipendente x WHERE x.nome = :nomeX");

		query.setParameter("nomeX", nomeDaCercare);
		results = (List) query.getResultList();

		return results;
	}

Abbiamo effettuato una ricerca sulla tabella che ha generato una lista di record.
Questi record ci vengono restituiti già mappati all’interno di diverse istanze della nostra
classe entity.
Ogni elemento della lista che ci viene restituita corrisponderà ad un record della tabella.

Il metodo getResultList() effettuerà la chiamata al DataBase e quindi il recupero dei dati.
Nel caso in cui stessimo cercando un particolare record, ad esempio tramite la sua chiave,
possiamo usare il metodo (sempre dell’interfaccia Query) getSingleResult()

 Dipendente dipendente = (Dipendente)em.createQuery("SELECT x FROM Dipendente x WHERE x.id_dipendente  =   :idDipendente")
											.setParameter("idDipendente", 100)
											.getSingleResult();

Potremmo anche recuperare solo un sottoinsieme dei campi di una tabella, tramite una JPQL specifica che
recuperi 1 o più campi.
Nel caso in cui si vogliano selezionare diversi campi di una entity è necessario creare una specifica classe
alla quale verranno mappati i risultati dell’esecuzione della query JPQL.
Nel caso di un solo campo possiamo semplicemente definire una Lista di oggetti (o un singolo oggetto) della classe che
verrà restituita dalla query JPQL.

  List matricole = (List)em.createQuery("SELECT x.matricola FROM Dipendente x WHERE x.nome  =  :nomeDaCercare")
											.setParameter("nomeDaCercare", "Alessandro")
											.getResultList();

Per finire questa breve introduzione alle basi dell’utilizzo del JPQL consideriamo il caso delle JOIN.
A differenza dell’ SQL in cui viene effettuato il join tra diverse tabelle per poi recuperare il/i campo/i che
ci interessano ,in JPQL possiamo recuperare una singola entità o una singola proprietà di un’entità.
Questo deriva proprio dalla natura della tecnologia JPA, infatti a partire da un’entità noi posssiamo recuperare
le istanze delle entità correlate , attraverso l’utilizzo dei metodi di get().
Se per esempio la nostra classe Dipendente fosse legata alla classe Settore :

public class Dipendente {

	@Id
	private BigDecimal id_dipendente;
	private Settore settoreLavorativo;
	....
	....
}

public class Settore {

	@Id
	private BigDecimal id_settore;
	private String denominazioneSettore;
	....
	....
}

Se volessimo conoscere il nome del settore in cui lavora un certo dipendente
potremmo semplicemente creare la seguente query JPQL :

  String nomeSettore = (String) em.createQuery("SELECT s.denominazioneSettore FROM Dipendente d JOIN d.settoreLavorativo s 
										WHERE d.id_dipendente = 123456 ").getSingleResult();

C’è da dire che non sempre è conveniente utilizzare le query JPQL , in questi casi possiamo comunque utilizzare le
chiamate native SQL e continuare sempre a lavorare con le entità java.
In ultima analisi possiamo facilmente comprendere come JPQL ci offra un potente mezzo per la gestione dei dati di un database
per tutte quelle applicazioni che utilizzano le Java Persistence Api.
La navigazione e le modifiche al database possono essere efettuate tramite delle operazioni su classi java (le entità) mappate
sul database che viene utilizzato, cio ci permette di utilizzare tipi di dato e costrutti java e di ottenere un livello di
astrazione che si interpone tra la struttura del database e il livello di logica business.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *