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 al CLASSPATH 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 directori libs dels arxius de projecte.

  • Incloure un arxiu persistence.xml al directori META-INF de l’aplicació. Pot crear el directori i afegir l’arxiu amb la configuració del mòdul JPA. Vincularem aquí l’arxiu hibernate.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’arxiu persistence.xml com a font de dades.

  • Aleshores podem demanar a aquest EntityManager que ens ofereixi un constructor de consultes CriteriaBuilder 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 com ORDER BY. De fet, es poden construir sentències extremadament complexes a partir dels diferents elements i mètodes que ofereix CriteriaQuery.

  • 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í:

 1 <?xml version="1.0" encoding="UTF-8" ?>
 2 <persistence xmlns="http://java.sun.com/xml/ns/persistence"
 3   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4   xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
 5  http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
 6   version="1.0">
 7 
 8   <persistence-unit name="mngr1" transaction-type="RESOURCE_LOCAL">
 9     <properties>
10       <property name="hibernate.ejb.cfgfile" value="hibernate.cfg.xml" />
11     </properties>
12   </persistence-unit>
13 </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.