Foro sobre Java EE > Uno o varios EntityManager en aplicación Java SE de escritorio
El EntityManagerFactory es un objeto que es thread-safe, pero que además es comptuacionalmente costoso de crear. Por otro lado, el EntityManager no es thread-safe y fácil de crear, pero además se supone que debería tener un ciclo de vida corto. Por esa razón creas una sola vez el EntityManagerFactory y a medida que vas necesitando un entityManager lo vas obteniendo del EMF. Ahora, que tu aplicación puede funcionar con un único EntityManager puede ser posible pero dependerá del caso. Solamente hay que aclarar que no es el uso esperado.
El asunto del caché compartido lo puedes resolver utilizando optimistic locking o bien manipulando directamente el caché a través de QueryHints (javax.persistence.cache.storeMode), utilizando anotaciones o mediante EntityManagerFactory.getCache().
Mira, me fuí a la literatura, y lo que encontré respecto a un EM generado manualmente en JavaSE es que te funcionará siempre y cuando no ejecutes EntityManager.close(), y además tienes que hacerte cargo del ciclo de vida de las transacciones. De todas formas deberás tener cuidado de no compartirlo entre distintos threads.
Muchas gracias por tus respuestas. La vida del EM no va a ser tan corta como en una aplicación web en la que se recibe la petición, se atiende y se acaba el proceso, porque las ventanas que se abrirán necesitan el EM desde que se crean hasta que se cierran. Al ser mantenimientos de tablas, pueden estar abiertas un par de minutos o media hora. Además, los procesos largos van a ejecutarse a través de SwingWorker, con lo que evitar que un EM único se acceda por múltiples hilos requeriría crear un hilo separado con el que cada tarea se comunicara, pero complicaría mucho el diseño de la interfaz (al menos para alguien que no trabaja 8 horas diarias con Java ni, en general, programando, como es mi caso).
No obstante, la aplicación normalmente va a ser monousuario y lo habitual es que sólo en algunos casos pueda haber posibilidad real de que el usuario tenga abiertas varias ventanas que accedan a los mismos datos. Tiraré por el EM por ventana con un único EMF creado al principio de la aplicación. Si encuentro alguna piedra en el camino ya lo contaré por aquí. :-)
Muchas gracias de nuevo.
Al ser mantenimientos de tablas, pueden estar abiertas un par de minutos o media hora.
Solamente ten cuidado de no mantener una transacción abierta tanto tiempo.
Una vez desarrollamos unas rutinas con JPA que corrían en JavaSE (en Tomcat y una Aplicación desktop) y nos fue de mucha utilidad el patrón "Command". Si tienes oportunidad revisa el capítulo 3 del libro "Professional Java - JDK 6 Edition" de Clay Richardson, Donald Avondolio, Scott Schrager, Matt W. Mitchell & Jeff Scanlon (Editorial Wiley).
Abundando un poco sobre el post anterior, la idea es que implementes una serie de métodos que sean la interfaz con tu lógica de negocios, e internamente implementas clases "Command" que serán ejecutadas por el "executor". El EntityManager y la delimitación de la transacción se llevan internamente, y tu aplicación desktop no tendría que manejar directamente estas estructuras. Si te interesa, te pongo un ejemplo.
Perdón, no había visto tus últimas respuestas, antoniovi.
Estoy revisando el código y creo que, sin saberlo, staba salvado. :) Uso NetBeans y su asistente de creación de nuevos archivos tiene la opción File -> New -> Persistence -> JPA Controller Classes from Entity Classes, que utilicé. Esto crea, para una entidad, una clase de apoyo que se encarga de proporcionar los métodos CRUD (con varios "R"). En todos ellos crea su propio EntityManager y lo cierra tras realizar la operación correspondiente,
El único riesgo es que el formulario tiene su propio EntityManager, pero de momento no he apreciado ningún caso en que éste no refleje los cambios hechos a través de la clase Controller. Aclaro, eso sí, y aunque ya sea estrictamente algo de Java SE, que los formularios los he hecho sin usar el asistente de NetBeans que utiliza BeansBinding, porque me daba más problemas de los que resolvía y queda menos "fino".
Miraré, de todas formas, el patrón Command. Muchas gracias por tus consejos.
Igual te interesa ésto: http://plugins.netbeans.org/plugin/53057/jpa-modeler
Ya sé que el título sugiere que esto debería ir en el foro de Java SE, pero como JPA se considera parte de Java EE, he decidido ponerlo aquí. Perdón si me he equivocado.
No acabo de encontrar una respuesta definitiva a si debería tener un único EntityManager para toda mi aplicación Java SE de escritorio, o si debería crear uno nuevo para cada "ventana" (opción de menú, JPanel ubicado en una pestaña, JInternalFrame... creo que el concepto está claro aunque no sea estrictamente una ventana).
He leído por ahí que EntityManager no es thread-safe, por lo que no debería tener una única instancia si voy a acceder desde distintos hilos (y así será, al tratarse de una aplicación Swing). Pero si abro uno para cada ventana, me preocupa que los cambios en un EntityManager no se reflejen en otros.
¿Alguien tiene experiencia en este escenario? ¿Si todos los EntityManager se crean desde el mismo EntityManagerFactory sería suficiente para compartir el caché?