Persistencia con EclipseLink 2.0

La Java Persistence Api (JPA) define como se debe crear un contexto de persistencia en una bbdd. Esto nos aislara del lenguaje nativo del motor de persistencia que estemos usando, y para nosotros solo seran objetos java (pojos) , que guardaremos, recuperamos, borramos, creamos... sin teclear (en la mayoria de los casos) ni una linea de SQL, lo cual nos abstrae de la bbdd que querramos usar (y esto es un alivio la verdad ).

Vamos a ver como configurar la implementacion de JPA EclipseLink.

Para ello, debemos importar la dependencia de dicha libreria en nuestro proyecto. Para esto hay que añadir  el repositorio de ElcipseLink y la dependencia como tal:

1. Añadiendo repositiorios a nuestro pom.xml:


<repositories>
       <repository>
           <id>EclipseLink Repo</id>
           <url>http://www.eclipse.org/downloads/download.php?r=1&amp;nf=1&amp;file=/rt/eclipselink/maven.repo</url>
      </repository>
 </repositories>

2. Añadiendo la dependencia de Eclipse Link

La dependencia de la JPA
  <dependency>
      <groupId>org.eclipse.persistence</groupId>
      <artifactId>javax.persistence</artifactId>
      <version>2.0.0</version>
    </dependency>


La implementacion que vamos a usar. EclipseLink

  <dependency>
      <groupId>org.eclipse.persistence</groupId>
      <artifactId>eclipselink</artifactId>
      <version>2.0.1</version>
    </dependency> 



Para conectar el eclipseLink con la bbdd necesitamos el driver de la bbdd. En este caso el Mysql:
 
<dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.0.5</version>
</dependency>

3. ANOTACIONES, este es opcional, pero a dia de hoy casi todo el mundo usa anotaciones en sus clases para mapear a bbdd. Se puede hacer con los ficheros de mapeo en XML, pero yo creo que en este caso esto es mas comodo.

Para usar anotaciones es necesario incluir este plugin en nuestro pom.xml:


<pluginRepositories>
            <pluginRepository>
              <id>maven-annotation-plugin</id>
                        <url>http://maven-annotation-plugin.googlecode.com/svn/trunk/mavenrepo</url>
            </pluginRepository>
</pluginRepositories>



 Una vez hecho esto podemos hacer un mvn install de nuestro proyecto para importar las librerias que 
necesitemos.

PARA EL USO DE ANOTACIONES ES NECESARIO COMPILAR CON LA VERSION 1.5 O SUPERIOR DE JDK

Si tu compilador de maven no esta especificado para que compile con la jdk 5, es necesario especificarlo en el pom.xml del proyecto, porque si no, las clases con anotaciones te daran fallo.
Para ello añadimos estas lineas en el pom.xml:

Creamos unas properties en el pom.xml (en caso de que sean varios modulos maven, interesa tener estas cosas centralizadas, mediante el uso de properties, asi que lo vamos a hacer asi):

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <maven-compiler-plugin.version>2.0.2</maven-compiler-plugin.version>
       <maven-compiler-plugin.source>1.6</maven-compiler-plugin.source>
       <maven-compiler-plugin.target>1.6</maven-compiler-plugin.target>
       <maven-eclipse-plugin.version>2.5.1</maven-eclipse-plugin.version>
       <maven-javadoc-plugin.version>2.6.1</maven-javadoc-plugin.version>
       <maven-resources-plugin.version>2.3</maven-resources-plugin.version>
       <junit.version>4.7</junit.version>
  </properties>

Vemos, que tenemos unas propiedades que especifican que codifique UTF-8 y el compilador a usar en la version jdk 1.6.
Tambien hemos añadido la version de junit, etc.....podriamos poner las dependencias que necesitaramos ,solo hay que buscar su referencia en los repositorios de maven.

Dentro de la etiqueta <build> de nuestro pom.xml se especifican los detalles que debe usar maven al compilar, paquetizar, etc.... (si no existe esa etiqueta en nuestro pom.xml, la creamos ) y dentro metemos esto:

<build>
           <pluginManagement>
            <plugins>
                <plugin>
                    <artifactId>maven-eclipse-plugin</artifactId>
                    <version>${maven-eclipse-plugin.version}</version>
                    <configuration>
                        <downloadSources>true</downloadSources>
                        <downloadJavadocs>true</downloadJavadocs>
                        <wtpversion>1.5</wtpversion>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>${maven-compiler-plugin.version}</version>
                    <configuration>
                        <source>${maven-compiler-plugin.source}</source>
                        <target>${maven-compiler-plugin.target}</target>
                        <encoding>${project.build.sourceEncoding}</encoding>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-resources-plugin</artifactId>
                    <version>${maven-resources-plugin.version}</version>
                    <configuration>
                        <encoding>${project.build.sourceEncoding}</encoding>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-javadoc-plugin</artifactId>
                    <version>${maven-javadoc-plugin.version}</version>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>

En el maven-eclipse-plugin, le estamos diciendo que use el plugin maven-eclipse-plugin cuando hagamos "mvn eclipse:eclipse", para integrar nuestro proyecto en el IDE Eclipse. Le decimos que opciones de compilacion debe decirle a eclipse que use, cuando importemos el proyecto. 
Vemos que le dice que descargue los fuentes de las librerias (dependencias ) que usemos y demas cosas...
Vemos que con ${nombre_propiedad}, nos aplica la el valor de la propiedad definida en el <properties>


El siguiene es maven-compiler-plugin, con este le especificamos con que jdk debe compilar y el encoding que debe usar (UTF-8).


El maven-resource-plugin le dice como tratar los archivos resources, en este caso le especificamos que use UTF-8 para todo.


 El maven-javadoc-plugin le dice como debe tratar y generar los javadoc.

Exiten muchos mas parametros y plugins para el build de maven, pero de momento solo necesitamos estos citados.


Ya podemos hacer mvn install de nuestro proyecto. (De momento no habiamos creado ni anotaciones ni pojos , ni nada, pero este paso sera necesario mas adelante, asi que si lo dejamos ya hecho, nos ahorramos muchos quebraderos de cabeza despues).


CONFIGURACION DE LA JPA (EclipseLink) 

La configuracion de nuestro motor de persistencia en la JPA, define que debe existir un fichero llamado persistence.xml dentro del path de nuestro proyecto (en la carpeta META-INF /persistence.xml) , para que lo pueda leer la libreria y levantar el contexto. (No es tan obligatorio que se llame asi, pero la recomendacion por defecto es esa, asi que no nos vamos a complicar):

En maven , estos ficheros son de tipo resource y por lo tanto lo crearemos en la ruta:

src/main/resources/META-INF/persistence.xml

(Cuando maven compile ya se encargara de meterlo en el path de nuestra aplicacion) 

PERSISTENCE.XML

Este fichero contiene toda la informacion relativa al contexto de persistencia, su url de conexion a bbdd, las clases que va a mapear con la bbdd, los timeouts, etc.....

Tendra un aspecto parecido a este:

<?xml version="1.0" encoding="UTF-8" ?>
<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_2_0.xsd"
        version="2.0" xmlns="http://java.sun.com/xml/ns/persistence">
 
<!--AQUI METEMOS EL NOMBRE DE LA UNIDAD DE PERSISTENCIA, PODEMOS TENER VARIAS, el nombre que queramos-->
<persistence-unit name="DppWare_Unit_Persistence">

       <!--ESTE ES OBLIGATORIO DE ECLISELINK, ES SU IMPLEMENTACION-->
        <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
 
     <!--AQUI PONEMOS LAS CLASES QUE QUERMOS MAPEAR CON LAS TABLAS, sera una lista de pojos en el futuro-->
        <class>org.dppware.persistence.entity.EntityUsuario</class>

    <!--PROPIEDADES VARIAS DE CONFIGURACION, vienen un poco explicadas, no hace falta ponerlas todas-->
        <properties>
    
        <!-- Configuracion para el driver de conexion . -->
            <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
            <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/churrera" />
            <property name="javax.persistence.jdbc.user" value="root" />
            <property name="javax.persistence.jdbc.password" value="root" />

            <!-- Optimize database writes to use batching. -->
            <property name="eclipselink.jdbc.batch-writing" value="JDBC" />
           
            <!-- Avoids flush being triggered before every query execution. -->
            <property name="eclipselink.persistence-context.flush-mode" value="COMMIT" />

            <!-- Configure connection pool. -->
            <property name="eclipselink.jdbc.connections.initial" value="1" />
            <property name="eclipselink.jdbc.connections.min" value="64" />
            <property name="eclipselink.jdbc.connections.max" value="64" />
 

            <!-- To drop and replace existing schema this can be used. -->
            <property name="eclipselink.ddl-generation" value="drop-and-create-tables" />

        </properties>
    </persistence-unit>
</persistence>

 Las marcadas en negro son las mas importantes. La verdad, es definir propiedades de nuestra bbdd, definir como queremos que se comporte la jpa (por ejemplo, le hemos puesto que cada vez que se instancie el contexto borre todas las tablas y las vuelva a crear, esto es muy util si estamos en fase de desarrollo del proyecto), etc...


<CLASS> Mediante este atributo le pasamos las clases que queremos que use para mapear directamente con la bbdd.  Hemos metido una llamada EntityUsuario.java. Vamos a ver su mapeo:

MAPEOS DE POJOs CON TABLAS 


Vamos a hacer un mapeo muy sencillo, luego se puede complicar lo que sea, pero eso ya es otro tema...

@Entity
@Table(name="
usuarios")
public class
EntityUsuario{

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
   
    private String name;
   
    public Integer getId() {
        return this.id;
    }

    public String getName() {
        return this.name;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public void setName(String name) {
        this.name = name;
    }

}


Vemos que tiene 2 propiedades, y sus propiedades  (siguiendo la java naming convention de Sun) los setters y getters, que utilizara la jpa (La jpa puede acceder a las propiedades a traves de sus getters y setters o directamente llamando a la propiedad, este comportamiento es configurable, pero yo prefiero a traves de getters y setters).


Anotamos la clase como entidad con la anotacion @Entity, con esto basta, pero esta anotacion tiene propiedades, para ello mirar las especificaciones de la jpa, ).
(una idea os podra dar la pagina de jboss hablando de hibernate, bastantes anotaciones y propiedades son compartidas por las implementaciones de JPA
http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html/entity.html )


Bueno, vemos que con las anotaciones @Table, le especificamos el nombre de la tabla que tiene que mapear con esta clase (si no le hubieramos especificado name, tomaria el de la clase).

Le decimos que propiedades tiene. Por defecto JPA intentara mapear todas las propiedades con las columnas de la tabla, a menos que se especifique lo contrario .

La propiedad @Id especifica que ese campo sera el identificador de la clase, por lo tanto ese debe rellenarlo la base de datos, que es la que conoce los id y sabe generarlos .
Mediante @GeneratedValue le decimos cual es la estrategia para generar ese id, en este caso le decimos que decida él el valor para nuestra primary key. (Este campo acepta mas valores, podriamos generar un identificador con 2 campos, o hacerlo de modo manual, etc.....hay mucha historia con los mapeos, busca un poquillo por internet).
Mira esta referencia para profundizar:
http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html/entity.html




Ya tenemos el contexto de persistencia y nuestro primer pojo.

CREAR CONTEXTO DE PERSISTENCIA  Y empezar a usarlo!!

Mediante este main testeador, vamos a instancia nuestro contexto de persistencia y veremos como se crea la primera tabla (ya que le especificamos, que creara las tablas al arrancar):

public static void main (String[]args){
//Le damos el nombre de la unidad de persistencia definida en el xml, y le decimos donde buscarla
//mediante el segundo argumento System.getProperties, que es una utilidad para leer ficheros en nuestro classpath

    EntityManagerFactory factory = 
               Persistence.createEntityManagerFactory("DppWare_Unit_Persistence",    System.getProperties());

//aqui obtenenmos el entity manager que nos va a dejar interactuar con la bbdd, es el encargado de realizar tareas de //grabado, lectura, transacciones, borrados, etc...
 
        em = factory.createEntityManager();

// NOTA : si consultamos la bbdd deberia de haberlos creado ya la tabla correspondiente  a nuestra clase pojo especificada , //EntityUsuario --> tabla "usuarios"

//grabado de datos: Creamos un objeto del tipo de la tabla y lo persistimos, asi mediante el entityManager

EntityUsuario user = new EntityUsuario();
user.setName("antonio");

        em.getTransaction().begin();
        em.persist(user);
        em.flush();
        em.getTransaction().commit();

//Si consultamos la bbdd, deberiamos tener ya el primer registro y vemos que ya tiene Id asignado
//deberia devolver el id generado, puesto que jpa actualiza ya esos campos al persistirlo
         System.out.println(user.getId);

//Para recuperarlo, no requiere de transaccion, asi que basta con 
    EntityUsuario userObtenido = em.find(entity.getClass(), user.getId());

//Para update, mas de lo mismo
        user.setName("breiker");
        em.getTransaction().begin();
        em.persist(user);
        em.flush();
        em.getTransaction().commit();

//Para borrado
        em.getTransaction().begin();
        entity = em.merge(entity); //Es necesario antes de borrar
       em.remove(entity); //tambien podriamos hacer primero un get
        em.flush();//El merge, mete la entidad dentro del contexto de persistencia si no esta
        em.getTransaction().commit();

}

La verdad, hay un monton de configuracion de parametros, mapeos de objetos a tablas, contextos de persistencia, etc.... Espero que tengas una vision un poco "general" de que va todo este asunto.

Comentarios

Entradas populares de este blog

Reiniciar usuario de SVN Subversion

Subir campos Blob a BBDD (Oracle) con Java

Reproducir mp3 con Java