Tabla de Contenidos
Ejemplo de JPA o Java Persistence API . JPA es el standard de Java encargado de automatizar dentro de lo posible la persistencia de nuestros objetos en base de datos .Sin embargo incluso a nivel básico genera dudas a los desarrolladores . Así pues vamos a dedicar algunas entradas del blog a hablar de los conceptos mas importantes.Para ello nos apoyaremos en el siguiente diagrama UML.
Persistence.xml
El primer concepto del que vamos a hablar es del fichero persistence.xml que se encuentra ubicado en la carpeta META-INF de un proyecto Java EE clásico . Este fichero se encarga de conectarnos a la base de datos y define el conjunto de entidades que vamos a gestionar.
<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_2_0.xsd" version="2.0"> <persistence-unit name="UnidadPersonas"> <class>es.curso.bo.Persona</class> <properties> <property name= "hibernate.show_sql" value="true" /> <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" /> <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" /> <property name="javax.persistence.jdbc.user" value="root" /> <property name="javax.persistence.jdbc.password" value="jboss" /> <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost/jpa" /> </properties> </persistence-unit>
En nuestro caso unicamente tenemos una entidad “Persona” y luego la parte que se encarga de definir el acceso a la base de datos generando un pool de conexiones etc.
De esta forma tendremos a nuestra disposición un EntityManagerFactory con el que empezar a gestionar las entidades que se encuentran definidas a nivel del fichero persistence.xml. Ahora bien muchas aplicaciones JEE se conectan a varias bases de datos y generan distintos EntityManagerFactorys
EntityManagerFactory
En un primer lugar un EntityManagerFactory es único y es con el que nosotros gestionamos todas las entidades. Ahora bien si tenemos varias conexiones a base de datos deberemos definir un nuevo concepto que nos permite clarificar que tenemos dos EntityManagerFactories distintos. Este concepto es el que se conoce como PersistenceUnit o unidad de persistencia. Cada PersistenceUnit tiene asociado un EntityManagerFactory diferente que gestiona un conjunto de entidades distinto.
De esta forma queda mas claras las diferencias entre persistence.xml, EntityManagerFactory y PersistenceUnit.
EntityManager
Una vez disponemos de un EntityManagerFactory este será capaz de construir un objeto de tipo EntityManager que como su nombre indica gestiona un conjunto de entitades o objetos.
En principio estas entidades son objetos POJO (Plain Old Java Object) normales con los cuales estamos trabajando en nuestro programa Java .El EntityManager será el encargado de salvarlos a la base de datos , eliminarlos de la base de datos etc . Para ello define otro concepto adicional “PersistenceContext” . Este concepto hace referencia a los objetos que han sido manipulados por el EntityManager y se encuentran controlados por él.
PersistenceContext
Para conseguir que alguno de nuestros objetos pase a ubicarse dentro del PersistenceContext bastará con invocar a alguno de los métodos típicos del EntityManager como persist , merge etc.
Ejemplo de JPA Conclusiones
Una vez un objeto se encuentra dentro del PersistenceContext el EntityManager será capaz de controlar todos los cambios que se han realizado en él y ejecutar las consultas adecuadas contra la base de datos. A continuación se muestra un ejemplo de JPA.
Cursos Asociados
package com.arquitecturajava; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; import es.curso.bo.Persona; public class Principal01Add { public static void main(String[] args) { Persona yo = new Persona("pedro",25); EntityManagerFactory emf = Persistence.createEntityManagerFactory("UnidadPersonas"); EntityManager em = emf.createEntityManager(); try { em.getTransaction().begin(); em.persist(yo); em.getTransaction().commit(); } catch (Exception e) { e.printStackTrace(); }finally { em.close(); } } }
En este ejemplo hemos usado el método persist() el EntityManager para almacenar la información en base de datos. Hemos tenido ademas que gestionar esta persistencia bajo en entorno transaccional . De tal forma que cuando se ejecute el método merge automáticamente pasemos a realizar un commit ( confirmación de la transacción) y los datos serán salvamos en la base de datos.
Saludos, alguien conoce las diferencias en la estructura de implementar JPA en Java SE y Java EE
En Java EE tienes capacidades de gestionar transacciones con anotaciones
Hola, a pesar de que este post es muy antiguo, me está sirviendo para comprender bastante mejor el funcionamiento y el concepto de los EntityManager/EntityManagerFactory/PersistenceContext….
Pero me gustaría preguntarte una duda.
Cuando un objeto ha sido manipulado por el EntityManager sea: em.persist(user), he observado que ya tenemos la id del usuario en este caso al realizar el persist, aún así hasta que no se realiza el commit no se verá reflejado en la base de datos.
¿El PersistenceContext se encarga de gestionar las ids que serán asignadas a la hora de guardar esos datos en la BD?
Muchas gracias por compartir tus conocimientos. Un saludo.
si hasta que no hagas commit , no se procesa nada contra la base de datos 🙂
Hola , le escribo ya que estoy aprendiendo jpa y estoy mirando que utiliza EntityManagerFactory para crear entity manager.Mi pregunta es que tipo de patron factoria utiliza.La abstracta ,la simple o method factory.
Calculo que use la Factoria , el que usa Abstract Factory es el Entity Manager
Hola, si tenemos un proyecto con la definición (persistence-unit) de nuestras conexiones de BBDD en el fichero “persistence.xml”. Si ésta misma definición de BBDD está configurada en el Servidor WebLogic donde corre la aplicación. ¿ Que debemos hacer en nuestro proyecto para no tener que definir todas las propiedades de cada conexión (url, user, password, etc) ? Osea queremos que el proyecto utilice las BBDD JDBC definidas en el Servidor WebLogic. Espero haberme explicado correctamente. Gracias.
Deberias usar una referencia JNDi al datasource que provee WebLogic.
He estado buscando algun ejemplo de fichero “persistence.xml” que esté configurado como dices, utilizando la referencia JNDI pero no encuentro nada clarificador. Si me pusieras un enlace a algún ejemplo seria de gran ayuda. Gracias.
https://gist.github.com/aziz781/1336488
Hola Cecilio,
He probado de configurar el persistence-unit tal y como creo que hay que hacerlo, pero sigo necesitando porner las properties (jdbc.driver, jdbc.url, jdbc.use y jdbc.password) en el fichero “persistence.xml”.
Otro problema que tengo en mi aplicación es la siguiente, son 4 WS que estan en un mismo paquete WAR que corren en un Weblogic 10.3.6.0. Cada uno de los WS utiliza una BBDD diferente y de vez en cuando alguno de ellos deja de funcionar y parece que lo que falla es la conexión de BBDD, pero accedo a la Consola de Weblogic y todo está correctamente. La única forma que conseguimos que vuelva a funcionar es parando y arrancando el nodo en el que están corriendo.
Te muestro uno de los mensajes por si sirve de algo:
Exception [EclipseLink-4002] (Eclipse Persistence Services – 2.3.1.v20111018-r10243): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLRecoverableException: Closed Connection
Error Code: 17008
Muchas gracias
Quizas estes gestionando en algún sitio incorrectamente las conexiones sin hacer los closes y entonces te acabas quedando sin conexiones en el pool
Hola, estoy haciendo el tutorial del libro (excelente trabajo) con un ejemplo mio, pero en vez de tomarme las anotaciones @entities, me toma los hbm. que estare haciendo mal?
No te se decir así con algo tan general, revisa que has desactivado los mapeos de los hbm en el fichero de configuracion
Este es el archivo persitence.xml (el archivo de hibernate.cfg.xml lo elimine)
Mi Unidad de persistencia
org.hibernate.ejb.HibernatePersistence
ar.com.sigeus.entities.Usuarios
ar.com.sigeus.entities.Cargos
Saludos, odras poner un ejemplo utilizando base de datos con mysql
Esta hecho con mysql 🙂 .. explicate un poco mejor 🙂
Hola por favor puedes explicar sobre el uso de procedimientos almacenados complejos en postgres utilizando jpa. Agradecere infinitamente tu ayuda 😉
ojala lo supiera todo alejandra me apunto la idea de los procedimientos almacenados con JPA 🙂
Saludos, puedes por favor indicar un ejemplo de como quedaría el archivo persistence.xml configurado con los dos datasources
algo así 🙂 http://www.mastertheboss.com/jboss-frameworks/hibernate-jpa/jpa-configuration/how-to-use-multiple-database-in-persistencexml
Buen aporte amigo. Muchas gracias por compartir.
gracias 🙂
Estimado he estado leyendo sobre las transacciones en JPA, y veo en tu ejemplo que usas explicitamente el begin , commit, rollback, pero tengo entendido que hay la opcion que las transacciones sean gestionadas por el contenedor automaticamente. Por favor puedes profundizar en el tema. gracias de antemano.
Cecilio, buenas, una consulta
Persona yo = new Persona(“pedro”,25);
EntityManagerFactory emf =
Persistence.createEntityManagerFactory(“UnidadPersonas”);
EntityManager em = emf.createEntityManager();
try {
em.getTransaction().begin();
em.persist(yo);
em.getTransaction().commit();
En mi caso tengo mas de una entidad mi consutlta es si por cada entidad que quiero persistir debo hacer el createEntityManagerFactory ?? que es lo que recibe como parametro ? en donde aqui entra en PersistenceContext?
Muchas Gracias.
Ah, tambien si eso de getTransaction es requerido antes y dsp de persistir_?
para iniciar y cerrar la transaccion
no hace falta . El createEntityManagerFactory solo se realiza una vez 😉
Hola, viendo tu comentario veo la nececiad de citar otro comentario:
“Tengo una duda en cada metodo por ejemplo update, select , save, etc. debo crear los objetos:
EntityManagerFactory emf = Persistence.createEntityManagerFactory(“UnidadPersonas”);
EntityManager em = emf.createEntityManager();
o puedo crear un singleton que me devuelva el emf o el em ? cual debo crear, actualmente estoy devolviendo el em, pero no se si sea lo correcto?”
en el comentario citado dices que no se debe tratar como un singleton, pero si el createEntityManager solo se realiza una vez, no seria mejor tratarlo como tal?, o en el caso de tener varias Entity Class de una base de datos, es necesario invocar de nuevo el createEntityManager o este sirve uno creado con anterioridad?
Aclaro, estoy refiriendome que cuando hay instancia de una unica base de datos.
y una duda extra, el em.getTransaction() retorna un UserTransaction? no es muy claro en la documentacion de java.
Me gusto tu post, es bueno tener ejemplos claros y sencillos ayudan a comprender mejor.
Puedes crear un singleton que devuelve emf pero no em 🙂 . El em no es un singleton
Como leo en anteriores comentarios tengo dudas sobre la creacion de la base de datos en cuanto a que es lo mejor diseñar y luego implementar directamente en un lenguaje tipo mysql o en JPA desde Java
en caso de lo hagas en mysql , hay que exportar esas tablas y crear sus clases entity , y por parte d elas validaciones donde es donde se aplicarian
A mi me gusta primero crear el modelo conceptual… que suele ser muy parecido al entidad relación y luego crear las tablas. Cuando luego generes el modelo de JPA puede que se te ocurra alguna idea con la que enriquecer la parte de base de datos. En cuanto a las validaciones recuerda que suelen estar divididas . Unas pertenecen de forma muy clara a la base de datos tipo claves primarias,foraneas, registros unicos etc pero otra parte de las reglas de negocio estan mas ligadas a los entities por ejemplo una Persona no puede tener mas de 120 años ..o cosas similares
Hola, muchas gracias de ante mano por esta explicacion.
Tengo una duda en cada metodo por ejemplo update, select , save, etc. debo crear los objetos:
EntityManagerFactory emf = Persistence.createEntityManagerFactory(“UnidadPersonas”);
EntityManager em = emf.createEntityManager();
o puedo crear un singleton que me devuelva el emf o el em ? cual debo crear, actualmente estoy devolviendo el em, pero no se si sea lo correcto?
muchas gracias por la ayuda que me puedas dar!!
Ninguno de los dos es un singleton y no deben tratarse como tal 🙁 .Quizás el EntityManagerFactory se acerca mas al concepto de Singleton ya que tenemos uno por unidad de persistencia. Sin embargo el EntityManager es muy claro que no es un singleton ya que existe uno por cada pequeño conjunto de operaciones.
Gracias, me fue de mucha ayuda.
de nada me alegro que te fuera util 🙂
Hola buenas tardes (por lo menos en Mx), primero que nada felicitaciones por el sitio recien me ha traido google por aquí y ya esta en mis marcadores. Yo desde hace tiempo trato de usar JPA por sus ventajas, pero me surge una duda, es posible cambiar el valor de las propiedades del archivo persistence.xml, esto es los datos de la base de datos? de momento tengo que cambiarlos y luego generar el .jar para que funcione con cada cliente, pero esto me parece poco practico, habitualmente trabajo con Delphi y aquí si puedo indicarle los datos de la base desde un archivo .ini
Agradesco de antemano tu tiempo.
Saludos!
Voy a intentar abordar este tema en un articulo del blog me parece interesante 🙂
Una pregunta tengo pensado migrar a web ya estos meses, cuando acabe de terminar algo con JavaFX, pero mi pregunta y mi inquietud se basa en, el html, css y js, en aplicaciones de escritorio como ya te dan todo para que solo empieces a arrastrar y soltar se hace muy fácil de dominar, pero en web lo he intentado y termina aburriendome tener que estar lidiando con tl html, css y js, existe bootstrap, pero para dominarlo tienes que tener las bases de las anteriores algo solidas y he visto también a jsf y es algo parecido pero por lo visto cuando se presenten problemas graves tendré que recurrir a las 3 primeras mencionadas ya que jsf es una abstracción de esos. Bueno espero darme a entender, tienes algún recurso de como integrar bootstrap con java web?
No tengo ningun recurso de bootstrap. Pero evidentemente JSF no sería el camino .Te aconsejo Spring MVC que de eso si tengo unos articulos de introducción en el blog.
Gracias!.
Que buen sitio, resumes rapido sin tanto alardeo y ejemplos claros, todo al grano. Veré en que más eres bueno felicitaciones por el sitio.
gracias 🙂
saludos… Como implementar como implementar la herencia de una clase abstracta en mi base de datos. Por ejemplo tengo una clase EventoDeportivo que tiene dos objetos “Contendiente” pero contendiente es una clase abstracta de la que heredan los contendientes concretos “perro”, “boxeador”, “equipo” pudiendo extender facilmente el uso de los contendientes en eventos deportivos. Mi pregunta es… cual seria el modelo relacional de dicho modelo de clases.
Yo empecé a usar jpa y anotar todas las clases con las anotaciones necesarias para mapearlas con el estándar. Pero cuando ejecuto la aplicación (java web con jsf, jpa) jpa en la base de datos sólamente crea dos tablas: “EventoDeportivo” y “Contendiente” y la doble relación, pero… además en la tabla “Contendiente” se agregan los campos raza (que pertenece al contendiente concreto perro), fechaFundacion(que pertenece al contendiente concreto equipo) y peso (que pertenece al contendiente concreto boxeador) y eso no me parece nada correcto.
Hay una anotación de JPA que te ayuda con clases abstractas @MappedSuperClass echala un vistazo 🙂
Oh que interesante! no los sabía. La estaré probando… gracias.
Una Pregunta
Siempre en las aplicaciones cliente/servidor y en las aplicaciones web me he preguntado si al realizar transacciones en ambos modelos / plataformas de programación es mejor
crear una sola conexión a la base de datos (en este caso una sola unidad EntityManagerFactory un solo EntityManager) o por cada transacción a realizar crear uno porque como en alguna parte explicas el modelo “guarda varias transansaciones” y las persiste todas al final con un commit cuando afirmas:”ya que el EntityManager irá almacenando las modificaciones que nosotros realizamos sobre las entidades .Para mas adelante persistirlas contra la base de datos todas de golpe ya sea invocando flush o realizando un commit a una transacción.”
Una idea o guía me ayudara muy bien.
Existe un unico EntityManagerFactory por PersistenceUnit . La que hace el EntityManager no es ejecutar una transacción por cada modificación que realizamos sino que lo que hace es almacenar todas las modificaciones que vamos realizando a los objetos para que cuando realicemos un commit el se encargue de lanzar las consultas pertinentes y refrescar la base de datos con las modificaciones solicitadas para mantenerlo todo sincronizado. No se si te he aclarado algo?
Saludos. Parece que hay mucho de JPA y JEE que tengo que descubrir. Me he fijado que los objetos quedan siempre en memoria.
Supongamos que tengo una lista de empleados en una vista (xhtml) cuyo value es un método “obtenerEmpleados()” de un ManagedBean que a su vez ejecuta al método con el mismo nombre, de una fachada de empleados, método que recupera los empleados con una consulta jpql. Desde la base de datos, borro o actualizo un empleado. Entonces al actualizar la vista se supone que debería faltar (ya no estar) el empleado que he borrado directamente desde la base de datos; pero, no es esto lo que pasa, el empleado siempre es encontrado y agregado a la lista. Tengo que limpiar alguna especie de caché o el contexto de persistencia? Agradecería mucho su ayuda.
en principio lo que deberias es volver a lanzar una consulta que vuelva a seleccionar la nueva lista y refresque los datos de la capa de presentacion .Date cuenta que el persistence context en principio tiene un ambito de Request
La consulta la hago nuevamente mediante la creación de un @NamedQuery, pero… cuando hago el singleResult(), el objeto es encontrado y devuelto al ManagedBean que a su vez se lo pasa a la vista.
Lo que hice fue usar el método evict(Class cls) de la cache del @EntityManagerFactory. Estoy conciente que no debe ser la mejor solución, pero… es la única manera en la que el objeto que ya no está en la base de datos tampoco sea encontrado en la consulta jpql
Saludos se que esta fuera de lugar, pero, quisiera saber si podría escribir sobre infecciones de dependencias.
Es algo que tengo pendiente y lo intentare en las proximas semanas
Hola,
Como puedo crear las tablas de la base de datos desde java, tengo todas las clases Entity java configuradas con sus relaciones, el persistence.xml, etc.
Existe un modelo de proyecto que se denomina JPA . Cuando construyes un proyecto de este estilo con eclipse el te aporta ese tipo de facilidades
Hola,
si como indicas, en caso de existir varias conexiones a base de datos aparece el concepto de “PersistenceUnit”, en este caso A y B. Entiendo que sigue existiendo UN SOLO archivo de configuración “persistence.xml” en el cual se pueden configurar varias persistenceUnit , ¿es así?
Gracias
Si exactamente con un único archivo es suficiente 🙂