En el post anterior hemos hablado sobre los distintos estados que una entidad puede tener dentro de JPA .En este artículo mostraremos el código de cada una de las operaciones básicas. Para ello nos apoyaremos en la clase Persona. En el siguiente bloque de código hemos usado las anotaciones de @Entity para identificar el bean como una entidad a guardar en la base de datos y @Id para identificar el campo de clave primaria. Por último hemos sobrecargado los métodos hashCode y equals a la hora de comparar objetos
package es.curso.bo; import javax.persistence.Entity; import javax.persistence.Id; @Entity public class Persona { @Id private String nombre; private int edad; public Persona() { super(); } public Persona(String nombre, int edad) { super(); setEdad(edad); setNombre(nombre); } public String getNombre() { return nombre; } public void setNombre(String nombre) { this.nombre = nombre; } public int getEdad() { return edad; } public void setEdad(int edad) { this.edad = edad; } @Override public int hashCode() { //simplificacion return nombre.hashCode(); } @Override public boolean equals(Object obj) { //simplificacion Persona nueva= (Persona)obj; return nueva.getNombre().equals(this.getNombre()); } }
Persist()
Ya vimos anteriormente el método persist pero vamos a volverlo a mostrar ya que es el encargado de almacenar nuevas entidades en base de datos.
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(); } }
Contains()
Como código complementario podemos apoyarnos en el método contains que comprueba si una entidad esta gestionada por el EntityManager devolviendo true o false según correspanda.
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(); System.out.println(em.contains(yo)); em.persist(yo); System.out.println(em.contains(yo)); em.getTransaction().commit(); } catch (Exception e) { e.printStackTrace(); }finally { em.close(); } }
Find()
Este método se encarga de localizar una Entidad a traves de su clave primaria. Para ello necesita que le pasemos la clave y el tipo de Entidad a buscar. Eso si recordemos que para que nos encuentre la entidad debemos haber sobrecargado los métodos equals y hashcode de forma correcta . En nuestro ejemplo hemos utilizado una implementación básica.
public static void main(String[] args) { EntityManagerFactory emf = Persistence .createEntityManagerFactory("UnidadPersonas"); EntityManager em = emf.createEntityManager(); Persona yo = em.find(Persona.class, "cecilio"); System.out.println(yo.getNombre()); System.out.println(yo.getEdad()); }
Remove()
Este método se encarga de eliminar una entidad de la base de datos.
public static void main(String[] args) { EntityManagerFactory emf = Persistence .createEntityManagerFactory("UnidadPersonas"); EntityManager em = emf.createEntityManager(); try { Persona yo = em.find(Persona.class, "cecilio"); em.getTransaction().begin(); em.remove(yo); em.getTransaction().commit(); } catch (Exception e) { em.close(); } }
Flush()
Este método es un poco mas curioso y es el encargado de sincronizar el PersistenceContext contra la base de datos .Normalmente todo el mundo piensa que cuando nosotros invocamos el método persist() o remove() se ejecutan automaticamente las consultas contra la base de datos .Esto no es así 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.
Otros artículos relacionados
- Un ejemplo de JPA Entity Graph
- JPA (III) EntityManager métodos
- JPA @ OneToMany
- JPA @ ManyToOne
- Ejemplo JPA
Disculpa buen amigo, por consultarle… mire yo estoy realizando un proyecto con JPA con tablas relacionadas en sí, 3 tablas(facruras, clientes, productos) y una de ellas se relaciona con las otras 2(productos y clientes), pero cuando edito por ejemplos productos no se edita, osea mando el ID pero me sale el registro no se actualizo y si le mando un ID que no esta en la base me sale que no existe y esta bien pero cuando le mando uno que si existe no lo edita… segun veo en el codigo ya que estoy trabajando con MYSQL y el modelo… Read more »
Prueba a usar algun tipo de cascade update , a ver si tienes más suerte.
Hola Cecilio, quería ver si tienes alguna orientación con mi siguiente situación Estoy usando eclipselink JPA para MYSQL le he puesto limite de espera tanto a persistence.xml, inclusive al QueryHints haciendo una prueba, bloqueo una tabla en MYSQL , pero a pesar de que mi servicio tiene configurado los tiempo de espera, en ningún momento suelta la petición, y puedo pasar horas, para que se despegue, lo que desenlaza quiebre del servidor. y tengo que reiniciar el GLASSFISH . inclusive después de horas, sin hacer nada no suelta, solo cuando desbloqueo la tabla en MYSQL retoma todo el control. pero… Read more »
No me ha quedado claro , pero da la sensación de que hay algo raro no deberias necesitar bloquear una tabla en mysql simplemente hacerla la consulta y luego asegurarte que cierras el entity manager para que la conexion vuelva al pool.
Hola estimado, aprendo de tus aportes, gracias. Solo por curiosidad, yo tengo armada una arquitectura pequeña que no es mía, si no de la empresa donde trabajaba, ahí yo solo me dedicaba a programar a nivel de negocio, pero ahora quiero entender como funciona, afortunadamente se que cositas van por allí y por allá, y con la inmensa ayuda de Netbeans, he logrado armar un proyecto pequeño. Ahora me gustaría si pudieras explicarme porque en mi proyecto las cosas son un poco distintas a tu explicación. Porque cuando uso : @PersistenceContext(unitName = “com.controlpersonal.pu”) private EntityManager em; Y luego : em.persist(object)… Read more »
Es una buena preguntan Andres intentare responderte las próximas semanas en el blog
Muy buen blog. Tengo un problema y es que cuando ejecuto el metodo remove() me elimina todas los registros de TODAS las tablas, solo le paso el objeto que quiero que elimine. No entiendo el problema. Una ayuda por favor?
Gracias
Es muy raro , pero podría ser que tengas configurado en el persistence xml que realice un drop y vuelva a generar todas las tablas cada vez que se ejecute algo.
Lo que puedes hacer es implementar un find() dentro del remove, o bien realizar el find() del objeto que quieres eliminar a parte, ej: Persona yo = em.find(Persona.class,yo.getId()); y em.remove(yo);
como guardaria un method. consulto por id y que me retorne un Email
no te entiendo bien , pero en principio si buscas por id , devuelve el objeto completo con todos sus campos
hola Cecilio primero que todo felicitarlo por tu pagina, quisiera saber como puedo eliminar un registro de una tabla que es autonumerico pero al mismo tiempo actualizar el registro. he agregado el metodo Find que se encarga de ubicar una entidad por medio de su Id pero no logro eliminar ese registro estoy manejando entityManager JPQL, espero me ayude.
Debería ser suficiente con un remove , pero para ello el bean debe estar manejado es decir le has tenido que seleccionar antes
Gracias Cecilio lo resolví creando un Query para eliminar el id asi: em.createQuery(“delete from Imagen where iddatos.iddatos=” + db.getIddatos()).executeUpdate();
me alegro 🙂
Hola gracias por tu post, tengo una pregunta.. actualmente estoy manejando una situacion asi:
Localidades -> Productos -> Precios
solo tengo un tema, con los precios ya que cada localidad maneja un precio diferente, ¿cómo pudiera relacionar eso, o que tendria que hacer para cuando precise una localidad, recuperar los productos que tiene y el precio correspondiente ?..
actualmente tengo un manytoone (Localidad ->producto) onetomany(Producto ->precios).., o sea todas las localidades ofrecen los mismos productos, pero su precio varia por localidad, cómo pudiera canalizar eso a traves de JPA, o me recomiendas que aplique JPQL ??.. gracias desde YA.
No se si te entiendo bien , pero lo que dices es que el precio varía por localidad para cada producto , no se pero a mi me da la sensación que te puede faltar una tabla tipo “AsignaciónPrecio” con fecha inicio y fecha fin?? y que el precio del producto varía con el tiempo y la localidad?. Es decir no puedes tener simplemente el último precio guardado ya que al imprimir una factura te saldrán con el precio nuevo. No se si te aporto algo? 🙂
Hola.
Gracias por la contestación.
Al final, edité la clase AbstractController, y en el método persist, introduje una comprobación adicional, comprobando el persistAction == PersistAction.CREATE.
Hasta este momento, solamente se comprobaba el DELETE. Los otros dos casos (CREATE y UPDATE) eran tratados del mismo modo, y por ello la creación de un nuevo registro se trataba como un UPDATE, aún cuando existiese ya una tupla en BBDD con esa primary key,
Ahora ya funciona correctamente.
Muchas gracias.
Un saludo
gracias por el aporte 🙂
Hola. Tengo un entidad llamada Cliente con un identificador llamado id, que es el DNI del cliente. Se crean correctamente los Clientes nuevos, se modifican correctamente y se eliminan satisfactoriamente los ya existentes. El problema es cuando intento crear un nuevo cliente con un DNI ya existe en BBDD. Lo que hace es actualizar el cliente existente en la BBDD, en vez de lanzar un error de Cliente ya existente. ¿Cómo puede estar ocurriendo esto, si el campo id lo tengo marcado como @Id y en la BBDD como primary key? ¿He de manejar esta situación en el método find?… Read more »
Debieras usar find para buscarle eso será lo más c´modo , aunque en principio si intentases usar persist para persistir algo que ya exista saltará una excepcion
para todo los que vamos entramos al mundo de Hibernate/JPA este es una excelente página!!
El tutorial es simple, rápido y muy útil!!!
gracias 🙂
como se llama tu libro, es que quiero ver si lo consigo en colombia
JPA Domain Driven Design
Hola Cecilio, tengo una entidad llamada Atencion, que contiene una relación con otra llamada recaudo, y esa a su vez contiene una lista de otro tipo de entidad…
cuando voy a guardarla por primera vez esta guarda en cascada a la perfección, pero cuando quiero hacerlo una segunda vez, esta no funciona, solo actualiza la entidad principal
alguna idea de que pueda ser??
saludos!
revisa las anotaciones de cascade.persist y cascade update
Hola Cecilio, tengo un tema en donde tengo dos schemas de base de datos mysql, uno para seguridad y otro para la parte de negocio. ¿necesito dos entityManager? ¿como se manejan estos casos?
Hola, tengo una duda, y es que estoy realizando una consulta que me retorna todo de esta manera:
CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
cq.select(cq.from(entityClass));
return em.createQuery(cq).getResultList();
Lo consulto la primera vez y sale todo OK, a la segunda voy a la base de datos, cambio algunos valores, y la vuelvo a ejecutar y me retorna los mismos valores de la primera ejecución….
a que se debe esto?
Estas manteniendo el mismo entity manager.. probablement este cacheando. Ejecuta em.refresh() a ver si tienes más suerte 🙂
Buenas, mi pregunta es como pudo modificar un objeto que tiene un id string, cambiando tambien el valor del id, he conseguido modificar un objeto pero dejandole el mismo id, si lo modifico me crea uno nuevo.
public void update (Article art, Article newArt) {//art es el articulo que quiero modificar y newArt los nuevos valores que tomara el articulo
EntityManagerFactory emf = Persistence.createEntityManagerFactory(“mvc_SourceExplicacionPU”);
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
//em.merge(art);
em.merge(newArt);
tx.commit();
em.close();
emf.close();
}
prueba a buscarle primero con find y luego modificarle con los nuevos valores
Hola Cecilio, saludos, tengo un problema desde hace días, estoy usando Entitymanager con Oracle, y me sucede que las búsquedas por primaria key usando el método Find funcionan correctamente, pero al usar una búsqueda con CreateaQuery no realiza la búsqueda y retorna nulo, pero si cambio la BD a Mysql o Postgresql si funciona correctamente. Que podrá ser?
Existen varios tipos de claves primarias autonumericas y no todas las bases de datos soportan lo mismo a nivel de jpa , tendras que echar un veo 🙂
Hola como estas, mira tengo una consulta, que pasa si tengo mi EntityManager y lo paso como parametro a otros metodos? es decir lo paso como referencia a metodos de mas bajo nivel.., hay algun problema con ello??
De entrada estarías compartiendo entre clases un objeto que gestiona un conjunto de entidades con su ciclo de vida. Estarías ampliando la vida del entity manager y normalmente esta no es su función ya que está orientado a gestionar el ciclo de vida de un pequeño grupo de entidades
Buenas cecilio, muy buen aporte, me dirias como hacer un find mas específico, es decir, uno que no busque solamente por Pk sino que si se cuample tal condicion me devuelva la/las insrtancias.
Para ello tienes que usar el entity manager y crearte una consulta con createQuery
property name=”eclipselink.cache.shared.default” value=”false”
Hola Cecilo, a la hora de actualizar (merge) una entidad no tengo problema, la modificacion se refleja en la base de datos al instante y tambien al hacer una consulta en el jtable. El problema esta en que cuando consulto esa modificacion desde otra sesion no actualiza. Tengo que volver a salir y entrar, y solo asi se actualizan los datos en mi aplicacion.
Estoy utilizando java swing y eclipselink.
Te agradeceria que puedas darme una mano. Espero poder comprar muy pronto tu libro. Saludos desde Paraguay.
Leyendo un poco pude darme cuenta que el problema estaba en que eclipselink tiene una propiedad de almacenamiento de cache. Esto sirve para que a la hora de consultar datos tu aplicacion no necesite acudir a la base de datos.
Esta es la propiedad que se deberia agregar al archivo de configuracion persintece.xml
“”
invoca al método refresh() de tu entitymanager
Hola, me podria explicar como se relaciona lo expuesto aca con por ejemplo HibernateUtil.java, es esta clase una implementación particular de JPAHelper.java? Adicionalmente que pasa con el persistenc.xml vs hibernate-config.xml?
Gracias.
Normalmente el hibernate util lo unico que hace es almacenar SessionFactory que sería lo mismo que almacenar EntityManagerFactory como singelton
¿Por qué es necesario sobrecargar los métodos hashCode y equals? En mi proyecto cojo las entidades desde las tablas de mi ORM cargando la base de datos. Estoy probando el método find de este tutorial y me pregunto porqué no funcionaría sin añadir esos métodos.
Hay en situaciones que hay que comparar por igualdad 2 objetos y en java dos objetos son iguales en principio si en memoria referencian a la misma instancia. Normalmente en un negocio se pide que dos objetos sean iguales si tienen el mismo idfactura o algo similar. De ahi la sobrecarga
Disculpa, una pregunta tonta, descargue el último código sobre JPA para poder verlo corriendo pero no puedo verlo funcionando, ¿como lo hago para poder probar la aplicación?
Tienes que instalarte una Base de Datos tipo mySQL y configurar el persistence.xml y el driver de coxexion. Mira este artículo https://www.arquitecturajava.com/ejemplo-de-jpa/
[…] Arquitectura Java :EntityManager Métodos […]
Hola, saludos. Yo tengo una consulta. Cómo se actualizan las entidades cuando se hace una transacción?. Por ejemplo, tengo 3 entidades. La entidad carga, almacena en cascada una lista de facturas. La entidad cliente, posee una lista de facturas. Así mismo cada factura está ligada a un único cliente. Si yo elimino una carga, elimino las facturas que fueron almacenadas durante la carga, pero siguen estando presentes en la lista de facturas del cliente. Así mismo, cuando guardo nuevas facturas o realizo un cambio, estas no aparecen en la lista de facturas del cliente. ¿Cual es la manera correcta de… Read more »
Has probado con el atributo Cascade Delete para borrar elementos padre /hijo . Es lo que se usa habitualmente. 🙂 Te permite si eliminas el padre que los hijos se eliminen automaticamente.
Saludos. Estoy teniendo una situación muy interesante con un proyecto de JSF y JPA. Estoy usando jpql. El negocio son las evaluaciones al personal. Cuando guardo un objeto evaluación, se guarda bien, cuando consulto evaluaciones todo bien, pero… cuando Guardo un objeto de evaluación y empiezo a consultar evaluaciones de una lista, en algunos registros, me aparece no la evaluación que estoy consultando, si no la que acabo de guardar. SIguiendo el error, llegué hasta la consulta donde me dí cuenta que los parámetros de la consulta los paso correctamente, pero la consulta jpql me envía un resultado que no… Read more »
No creo que sea problema del framework yo creo que es algo que se te ha escapado .Recuerda que JPA se centra mucho en los objetos . Has escrito correctamente los métodos hashcode e equals? ya que sino están sobrecargados pueden devolverte resultados que no eran los que buscabas.
Ahora, usando la aplicación el problema no ha aparecido mas. :/ Ya no se está dando, pero no me da buena impresión, porque como sabemos no hay magia. Revisaré bien las entidades. Muchas gracias.
Bueno puede ser que algo te estuviera cacheando o similar .Esas cosas pasan 🙂
Don Cecilio muchas gracias. Lo resolví eliminando la caché de las entidades “entidadEspecífica” del EntityManagerFactory con el método EMF.getCache.evict(class);
Me he perdido un poco con todos los comentarios 🙂 al final lo resolviste ?
Un saludo
Incluso estuve teniendo un situación en la cual Yo tenía una lista de objetos. Alguien desde otra vista o directamente desde la base de datos elimnada un registro (un objeto de esa lista). Cuando yo hacía un find de esa entidad con JPA el objeto siempre era retornado en la lista, aparentemente porque permanece en el contexto de persistencia. Entonces… tuve que ir a vaciar la caché siempre que lo consultaba para obligar a JPA a buscarlo en la BD
hola todos los tutoriales son muy bien explicados, eh estado leyendo el libro y la verdad esta muy bien, soy de mexico DF y me gustaria comprarlo pero en las principales librerias de mexico no lo encuentro :'( espero llegue pronto, gracias por todos los aportes eh aprendido muchas cosas que se me dificultaban saludos
Al final me parece que solo esta disponible via Amazon . Ya lo siento pero cuando lo publique no pensé que tendría tanto éxito. Espero a futuro ir aprendiendo de estas cosas.
Hola!, primeramente felicitarte por los tutoriales, queria pedirte si se puede subir la forma de mapeos para las relaciones Unidireccional y Bidireccional en JPA.
Gracias!!
Si tengo tiempo intentaré publicar algo sobre esos temas . Gracias por la idea 🙂