Sisena part del curs Curs BBDD i Java centrada en la millora de les tècniques presentades en el punt anterior. En concret s’estudia el component de Java de persistència JPA i com podem combinar-lo amb tècniques vistes fins ara.
1. Introducció a JPA
Hibernate ofereix una classe nova, més eficient que Criteria
, anomenada CriteriaQuery
que va més enllà i permet realitzar tasques complexes sobre les dades de les taules.
Per utilitzar la classe CriteriaQuery
s’ha de fer servir el mòdul JPA (Java Persistence API) que permet associar objectes a fonts d’informació diverses (base de dades, arxius XML, etc.) en un model semblant al presentat fins ara.
Per utilitzar les funcionalitats de JPA combinades amb Hibernate necessitem:
-
Incloure un API de JPA per accedir a les seves funcionalitats combinades amb Hibernate: Això ho podem aconseguir afegir l’arxiu
hibernate-entitymanager-4.1.8.Final.jar
alCLASSPATH
de la nostra aplicació (disponible des de la descàrrega del API de Hibernate) o copiar-lo a un directori local de l’aplicació. En el nostre cas s’ha inclòs en el directorilibs
dels arxius de projecte. -
Incloure un arxiu
persistence.xml
al directoriMETA-INF
de l’aplicació. Pot crear el directori i afegir l’arxiu amb la configuració del mòdul JPA. Vincularem aquí l’arxiuhibernate.cfg.xml
per a què tingui en compte la configuració de Hibernate com a font d’informació per a JPA. -
Des de l’aplicació haurem d’invocar la creació d’un
EntityManager
que gestioni les consultes amb la base de dades. Per fer-ho haurem d’executar un codi com el següent:EntityManagerFactory emf = Persistence.createEntityManagerFactory("mngr1"); EntityManager em = emf.createEntityManager(); ...
El nom
mngr1
ha de coincidir amb aquell declarat en l’arxiupersistence.xml
com a font de dades. -
Aleshores podem demanar a aquest
EntityManager
que ens ofereixi un constructor de consultesCriteriaBuilder
i que farem servir per construir consultes contra la base de dades (o l’origen de dades establert en el JPA):... CriteriaBuilder cb = em.getCriteriaBuilder(); ...
-
Per a construir una consulta de selecció amb aquesta metodologia JPA, podem executar codi com el següent:
CriteriaQuery<Employee> query = cb.createQuery(Employee.class); Root<Employee> emp = query.from(Employee.class); query.where(cb.equal(emp.get("lastname"), "King")); query.orderBy(cb.asc(usuari.get("firstname"))); List<Employee> result = em.createQuery(query).getResultList();
Com veu es poden afegir restriccions de tipus
WHERE
i clàusules comORDER BY
. De fet, es poden construir sentències extremadament complexes a partir dels diferents elements i mètodes que ofereixCriteriaQuery
. -
Per executar tasques DML sobre les dades, hem d’iniciar una transacció. Això es pot fer amb codi com el següent:
... em.getTransaction().begin(); ... // operacions DML ... em.getTransaction().commit(); // ...o rollback(); ...
Per executar una consulta de modificació podem utilitzar diversos mètodes, entre els quals destaquen:
-
Consultes JPQL (Java Persistence Query Language):
Query q = em.createQuery( "UPDATE Employee e SET e.salary = 18000 WHERE u.lastname='Rovirosa'"); q.executeUpdate();
-
Vincular l’objecte que reflecteix les dades (fer-lo managed) i modificar-lo en memòria:
Employee anna = em.find(Employee.class, 214); anna.setSalary(18000);
La primera operació ha importat les dades des de la base de dades a un objecte local en memòria. Qualsevol operació sobre l’objecte serà traslladada a la base de dades quan s’efectuï l’operació de COMMIT
per finalitzar la transacció. A aquest fet s’indica que l’objecte importat passa a l’estat managed, indicant que a partir d’aquell moment correspon a dades reals de base de dades i queda vinculat a la seva font d’informació. Per això no cal realitzar tasques addicionals amb l’objecte per modificar-lo: simplement trobar-lo amb find()
, modificar-lo i finalment fer el commit()
.
2. Exemple amb JPA + Hibernate
S’ha fet una nova versió del bloc de programes de prova per demostrar l’ús de JPA combinat amb Hibernate.
Observi ara l’exemple número 8
Podrà observar que l’estructura d’arxius és gairebé idèntica a la vista anteriorment, però ara s’incorpora el directori META-INF
amb l’arxiu de configuració persistence.xml
al seu interior. Aquest arxiu correspon a la configuració de JPA, i que en el nostre cas és com es mostra aquí:
Arxiu persistence.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
<?xml version="1.0" encoding="UTF-8" ?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
version="1.0">
<persistence-unit name="mngr1" transaction-type="RESOURCE_LOCAL">
<properties>
<property name="hibernate.ejb.cfgfile" value="hibernate.cfg.xml" />
</properties>
</persistence-unit>
</persistence>
Observi que aquest arxiu només s’encarrega de declarar una unitat JPA anomenada mngr1
i que es faci ús de la configuració present a l’arxiu hibernate.cfg.xml
com a font d’informació per a l’origen de dades.
En realitat aquest arxiu també podria contenir tota la informació en el seu interior (driver, usuari, base de dades, etc.) però s’ha preferit mantenir l’arxiu separat per claredat.
La resta d’arxius dels programes de mostra estan pràcticament iguals, només canviant el DAO per adequar-lo a les característiques de JPA.
Observi que el DAO conté una funció anomenada setUp()
, que omple dues variables clau per a l’ús de JPA des de l’aplicació. El seu objectiu és habilitar JPA i iniciar un objecte de tipus EntityManager
que anomenem em
i un altre de classe CriteriaBuilder
que anomenem cb
. Gràcies a aquests dos objectes podrem accedir i manipular les dades de la base de dades. Aquesta funció és cridada tot just iniciar-se el programa.
Com veu, la càrrega programàtica d’aquesta modalitat és menor. JPA és un API optimitzat per a l’accés a informació que resideixi en multitud de possibles orígens de dades i es fa servir en bona part del desenvolupament d’aplicacions reals.