Sie sind auf Seite 1von 13

Introduccion a JPA (Java Persistence API)

Publicado octubre 20, 2008 Java , Programacion 58 Comentarios

Vamos a programar un poco


Antes cuando tenia que hacer una consulta en la base de datos, empleaba
JDBC a pelo o Frameworks como iBatis e Hibernate. Eran APIs que permiten
mapear una clase Java (Bean) con una tabla de la base de datos y facilitan
mucho el trabajar con la persistencia de los objetos (usando metodos del estilo
a select, insert, update y delete).
Pero ahora he conocido JPA y me parece que a partir de ahora sera lo unico
que utilizare. Con JPA puedes hacer cosas como estas:

- Escribir el codigo de tu clase, y aunque no exista la tabla correspondiente en


la base de datos, no importa!!. JPA se encargara de crear la tabla del modelo
de datos. Esto esta Genial!!!, es decir, tu solo escribes el codigo y JPA con su
mecanismo de persistencia ya se encargara de crear la tablas, si no existen y
si existen pues las usa. Ademas da igual la base de datos, podrias por ejemplo
escribir la aplicacion en MySQL y despues con un ligero cambio llevartela a
Oracle.

- Sincronizacion. Viene tu jefe de proyecto y te dice, quiero que aadas dos


columnas nuevas a esta tabla y elimines el campo primario de esta otra tabla.
Y ya empiezas a sudar. Llevas escritas mas de 20 sentencias SQL y te toca
cambiarlas. Eso se acabo. Es tan sencillo como irte al codigo de tu bean, y
aadir 2 atributos nuevos que se mapearan como campos nuevos de la tabla.
Chachi.

- Puedes tambien mantener la persistencia no necesariamente atacando a una


base de datos, tal vez te interesaria persistir un objeto a un fichero de texto
plano o XML.

Como ejemplo de uso de JPA vamos a implementar un pequeo


sistema CMSpersonal. La idea es escribir una pequea aplicacion que nos
permita almacenar nuestros documentos en la base de datos. Y al decir
almacenar me refiero a almacenar el contenido del documento en la propia
base de datos, no su pathname o ruta en el disco duro. De esta manera
aprovecharemos para ver como con JPA se hace tambien muy simple la
insercion en campos BLOB de la base de datos, algo que muchas veces trae de
cabeza a los desarrolladores de Java.

Este ejemplo de CMS (cuyo codigo dejo al final del articulo) sera muy simple.
He preferido que el ejemplo no se complique con restricciones o constraints de
la base de datos, asi que no existen tampoco claves foraneas a otras tablas.
De manera que sera dificil que nos de un error, cuando intentemos insertar
algun contenido. Tambien en esta primera version solo os dejare una
aplicacion en modo consola (un interprete de comandos) que nos permitira ir
insertando o consultando los documentos de nuestra base de datos. En otro
articulo posterior, veremos como crear un interface grafico via web que nos
permita manipular los documentos.
Que necesitamos?
- Pues un editor de Java. Puedes usar el que mas rabia te de. Eclipse,
Netbeans u otro. Yo esta vez he usado Netbeans, para ir variando.
- Una base de datos. El ejemplo esta preparado para MySQL pero funcionara
con ligeros cambios en Oracle u otra base de datos relacional. A su vez, no te
olvides de incluir el driver JDBC de conexion a la base de datos en el
Classpath.
- y por ultimo y lo mas importante, para trabajar con JPA necesitamos una
implementacion de JPA. Existen muchos fabricantes que han hecho la suya
(verimplementaciones). En el ejemplo yo he empleado EclipseLink, asi que
basicamente, descargate esta implementacion, descomprimela y copia los
siguientes .jar en el classpath de tu proyecto:
- eclipselink.jar
- javax.persistence_1.0.0.jar

En Netbeans podemos por ejemplo crear una Libreria con esos jar, que luego
incluiremos en el proyecto, en Eclipse, pues bastaria con aadirlos al classpath.

Ya tenemos todo lo que necesitamos para trabajar, pero no esta de mas que te
bajes la siguiente tarjeta de referencia de JPA.
Y ya puestos, la siguiente, que nunca esta de mas.

JPA trabaja fuertemente con anotaciones. Para mapear un bean (una clase
java) con una tabla de la base de datos, tendriamos que escribir lo que se
llama un Entity.
Esto es tan sencillo como escribir nuestro Bean, con sus atributos y metodos
get y set. Y despues aadirle la anotacion @Entity a la par que
seleccionamos uno de sus atributos como clave primaria con @Id. Por
ejemplo, el siguiente trozo de codigo podria ser un Entity, que nos permitiria
luego almacenar, recuperar, o actualizar campos sobre una tabla usuario:
@Entity
public class Usuario
{
@Id
private String id;
private String name;
private String email;
}

Con solo esto ya tenemos creada una entidad llamada Usuario y podriamos
insertar, actualizar o eliminar entradas en una tabla llamada Usuario aunque
esta aun no existe, siquiera. A que mola!!

Un fichero muy importante que tenemos que crear a parte de las clases
Entity es el fichero persistence.xml, en este fichero vamos a indicar
precisamente que clases son Entity, sobre que base de datos vamos a atacar, y
cual es la politica de creacion de esta base de datos.
Este fichero persistence.xml debe colgar de un directorio META-INF que
este accesible en el CLASSPATH. Esto es, si tu codigo por ejemplo lo estas
dejando en la carpeta src, tendras que crear una carpeta src/META-INF y
ahi dentro crear el fichero persistence.xml.
El contenido de este fichero es similar al que puedes ver en la siguiente
imagen:

Fijate en el XML un momento:


- Tiene un nombre DOCSPU en el tag , este es importante, pues luego es por
ese nombre por el que podremos acceder a este recurso o unidad de
persistencia. Aqui se llama DOCSPU pero puedes darle el nombre o alias que
quieras.

- Entre y vamos aadiendo todas las clases Entity que queremos manipular.
Esto tambien es muy importante, porque si creas un Entity pero no lo aades a
esta seccion del XML, para JPA no existe.

- Y por ultimo estan los properties. En estos properties estamos definiendo el


mecanismo de conexion a la base de datos. Cambiando estos valores por los
adecuados podemos conectar a cualquiera otra base de datos que tengamos.

- Existe una ultima propiedad que conviene tener activa en los primeros
momentos, cuando estamos desarrollando:

Esta propiedad hace que si el modelo de datos no existe se cree de manera


automatica, pero cada vez que invocamos al mecanismo de persistencia, borra
el contenido de las tablas y las vuelve a crear si no existen previamente. Esto
al comienzo cuando estamos de pruebas viene de fabula, despues ya
podemos comentar esta opcion para trabajar con datos reales que tengamos
insertados.

Tenemos los Entity ya creados. Como puedo por ejemplo, insertar uno de ellos
en la base de datos.
Pues con un trozo de codigo similar al siguiente:

- Primero creamos un EntityManager que nos permita manipular y trabajar con


los objeto Entity:

String UNIDAD_DE_PERSISTENCIA = "DOCSPU";


EntityManagerFactory factory =
Persistence.createEntityManagerFactory(UNIDAD_DE_PERSISTENCIA,
System.getProperties());
em = factory.createEntityManager();

Como ves, el nombre que uso es DOCSPU, esto es porque asi lo tenemos
definido en el fichero persistence.xml, asi sabe como recuperar las clases y
propiedades que corresponden a esta unidad de persistencia. Si tu cambiaste
el nombre en el XML, aqui deberias poner el que hayas usado.

Una vez creada la EntityManager, ya es muy simple, abrir una transaccion e


incluso almacenar elementos (Entity) en la base de datos. Un ejemplo para
insertar un Usuario podria ser:

em.getTransaction().begin();
Usuario u = new Usuario();
u.setId(100);
u.setName("jose");
u.setEmail("notengo@gmail.com");
em.persist(u);
em.flush();
em.getTransaction().commit();

Como observas, hemos recuperado una transaccion (getTransaction),


instanciado un objeto usuario, asignado valores a sus atributos, lo hemos
persistido (almacenado) en la base de datos con persist y por ultimo un
commit de la transaccion.

Es decir, solo escribiendo una clase, y un XML, ya hemos insertado un usuario


con campos nombre y email en una tabla Usuarios que se ha generado de
manera dinamica. No te parece ideal?.
No hay que escribir metodos, insert, update ni delete, ni crear el modelo de la
tabla si no nos interesa. Todo se hace dinamicamente.
Consultas:
Para hacer las consultas en JPA se emplea un lenguaje denominado JPQL, no
es SQL exactamente porque trabaja con objetos no con columnas pero si
muy parecido.
Por ejemplo, si la consulta de todos los campos de una tabla es SELECT *
FROM USUARIOS, en JPQL la consulta seria SELECT u FROM Usuario u,
Donde Usuario no es el nombre de una tabla, sino de la clase Entity y u
son los identificadores del objeto.
Mas ejemplos: SELECT u.id,u.name FROM Usuario u where u.name LIKE :=
PARAMETRO.
Es muy parecido a construir un PreparedStatement donde pasamos los
parametros.
Para ejecutar estas consultas empleamos el objeto Query. Query admite dos
metodos:
- getResultList, cuando el conjunto de valores devuelto es una lista de
valores, por ejemplo un SELECT de varios campos.
- getSingleResult, cuando solo se devuelve un unico objeto (fila).

Por ejemplo para obtener Todos los proyectos de una tabla Proyectos:

Query q = em.createQuery("SELECT p FROM MdcoreProject p");


List<MdcoreProject> proyectos = q.getResultList();
int num_proyectos = proyectos.size();

Si quisieramos ejecutar consultas con parametros, las variables a sustituir van


precedidas de : y debemos pasarlas con setParameter. Ejemplo: una
consultas de proyecto cuyo proyecto es 666 seria:

Query q = em.createQuery("SELECT p FROM MdcoreProject p WHERE p.id


: = PROYECTO_ID");
q.setParameter("PROYECTO_ID","666");
MdcoreProject mi_proyecto_buscado = (MdcoreProject)
q.getSingleResult();

Como veis, estamos trabajando con objetos no con clausulas SQL.

Y tenemos que tener esas consultas JPQL embebidas en el codigo?

Pues aqui tenemos otra ventaja de JPA, Si no queremos, no tenemos porque.


Podemos si queremos definir anotaciones con las sentencias SQL en el
cuerpo del Entity, estas sentencias SQL se indicarian con la anotacion
@NamedQuery. Un ejemplo:

Fijate en el codigo del Entity, es una clase llamada MdcoreUser que


implementa los datos de un usuario. Con @Entity ya indicamos que es una
entidad. con @Table ya forzamos a que se mapee con una tabla llamada
MDCORE_USER, en caso de no usar la anotacion @Table, el nombre de la
tabla creada se llama exactamente igual al nombre de la clase java.

Con la anotacion @NamedQueries vamos indicando las diferentes sentencias


SQL que queremos utilizar, bueno, perdon sentencias JPQL. Y esto es
fantastico otra vez, pues al ser anotaciones, podemos cambiarlas sobre la
marcha. Aqui aprovecho y comento otras anotaciones de las que no habia
hablado, ya vimos que con @Id vamos indicando que columnas son clave. Pues
bien con @GeneratedValue podemos indicar si queremos que los campos clave
se creen de manera automatica, por ejemplo mediante el uso de secuencias.
En otro caso, somos nosotros los que debemos calcular el valor de un nuevo id
cuando vayamos a insertar. Otra anotacion es @Column nos permite asociar
un atributo a un nombre de columna en particular. Por ejemplo tenemos un
atributo llamado fxCreacion pero en la base de datos la columna se llama
FECHA_CREACION. En caso de no indicarlo, las columnas de la tabla se
llamaran igual que el nombre del atributo del Entity.

En el caso de que queramos usar las anotaciones @NamedQuery, si que


cambia un poco la forma de invocar a Query que vimos un poco mas arriba.
y es que en este caso, en lugar de usar un createQuery(String con el JPSQL),
debemos usar
createNativeQuery(nombre_de_la_anotacion_namedQuery_definida_en_el_En
tity).

Por ejemplo si tuvieramos:

@NamedQuery(name = "MdcoreUser.findById", query = "SELECT s FROM


MdcoreUser " +
"s WHERE s.id = :id")

La consulta podria ser:

Query q = em.createNativeQuery("MdcoreUser.findByID");
q.setParameteR("id","100");
MdcoreUser u = q.getSingleResult();

En este punto tambien comentar que en estos entornos de desarrollo (Eclipse,


netbeans) puede hacerse el paso inverso, es decir, a partir de una base de
datos, generar el Entity correspondiente. A este proceso se le llama Ingenieria
inversa. Pero no lo cubriremos en este articulo.
Podeis de todas formas obtener mas informacion en el sitio de Eclipse o
enNetbeans. De todas formas, pienso que lo mas comodo es escribirlo uno
mismo (ademas el Entity es un simple bean).
Ejemplo CMS:

Como se que esto al principio es complicado, aunque luego se le pilla el truco.


Os dejo unos cuantos ficheros fuente con un ejemplo de aplicacion JPA. Solo
incluyo los fuentes, para que no pese mucho, los .jar correspondientes a
EclipseLink y driver JDBC debeis colgarlos vosotros.

Esta pequea aplicacion es un interprete de comandos que nos permite


insertar documentos en la base de datos en base a tags, por ejemplo
podriamos insertar un documento Introduccion a JPA.pdf bajo los tags
Programacion,Java,JPA. Consultar documentos en base a su tag (p.ej
devolver todos los documentos almacenados que sean de la categoria:
Oracle) y descargar documentos.

Usa varias tablas, pero la mas importante es MdcoreDocs. Realmente las


demas son solo para un desarrollo a mayor nivel. Las tablas son:

- MdcoreUser, Guarda informacion de los usuarios


- MdcoreProject, Guarda informacion de los proyectos
- MdcoreMetadata, Guarda metadatos del proyecto (p.ej DOCUMENTOS,
SCRIPTS)
- MdcoreTags, Tags de los diferentes docs (Oracle, Java, Bases de datos,
MySQL, etc..)
- MdcoreDocs, Los documentos almacenados en la base de datos.
- MdcoreSetDocTags, Permite asociar documentos con tags
Para simplificar no hay relaciones activas entre tablas, y por defecto cuando se
inserta un documento en la base de datos, se asigna de manera automatica a
un proyecto=0, usuario=1, metadato=1
(el proyecto 0 vendria a ser: DEFECTO).
El interprete de comandos se lanza con la clase MyDocs. Este seria por ejemplo
una sesion donde almacenamos un documento en la base de datos:

Y aqui el resultado de insertar en la base de datos (nota que no he creado el


modelo de datos, se crea de manera automatica):

Un Blob insertado en MySQL de la manera mas rapida y sencilla posible ^^

Este ha sido un tutorial muy basico, unicamente para que conozcais esta API y
tal vez os sirva de ayuda para empezar a mapear vuestros Entity. no creo que
siga con los tutoriales, pero con JPA se pueden hacer cosas mas complejas y
establecer asociaciones 1 a 1 y 1 a M entre las tablas. Esperemos queHermoso
dia se anime y continue con algun tutorial mas avanzado. (Gracias Lechuck por
ensearme este API).

Como prometi, aqui los fuentes (estan como .pdf realmente son .tar, renombra
de .pdf a .tar y descomprimelos, los subo asi, pq wordpress solo dejar subir
pdfs e imagenes).

http://ubuntulife.wordpress.com/?s=jpql

Das könnte Ihnen auch gefallen