java - example - persistence context
JAVA: un objeto EntityManager en un entorno multiproceso (5)
si tengo varios hilos, cada uno usa un inyector para obtener el objeto EntityManager, cada uno usa el objeto em para seleccionar una lista de otros objetos de clase. Listo para ser utilizado en un bucle for.
Si un hilo termina primero y llama a clear (), ¿afectará eso a los otros hilos? ¿Como el bucle for tendrá una excepción?
¿Qué hay de cerca ()?
Si la respuesta es "Depende", ¿qué (definición de clase? ¿Método de llamada?) Y dónde (¿código de Java? ¿Anotación? ¿Xml?) ¿Debo consultar para saber cómo se depende?
No escribí la fuente, solo uso la biblioteca de otra persona sin documentación.
Gracias.
Estoy fuera por tres años más o menos :), pero en cuanto a inyectar EntityManager en EJBs, aquí hay un enlace a la entrada del blog de Adam Bien http://www.adam-bien.com/roller/abien/entry/is_in_an_ejb_injected
copiando-pegando desde allí:
"Puede inyectar EntityManager directamente en EJBs. Pero, ¿es seguro para subprocesos ?:
@Stateless
public class BookServiceBean implements BookService {
@PersistenceContext EntityManager em;
public void create(Book book) { this.em.persist(book);}
}
"
y la respuesta es, nuevamente copiando-pegando:
"Trabajar con EJB sin ninguna configuración adicional es seguro para subprocesos independientemente de si está invocando un método o varios métodos a la vez. El contenedor se preocupa por la serialización de las llamadas".
lo que quizás podría ser más claro, pero implica que puede inyectar EntityManager en beans de sesión sin estado, y no estar preocupado por los problemas de concurrencia de EntityManager.
Hay dos tipos de administración de EntityManager: administrado por contenedor y administrado por aplicación. Para la aplicación administrada, el método preferido para obtener EntityManager es a través de EntityManagerFactory. El tutorial de Java EE dice esto:
Gestores de entidades gestionadas por contenedores
Con un administrador de entidades gestionado por contenedor, el contexto de persistencia de una instancia de EntityManager es propagado automáticamente por el contenedor a todos los componentes de la aplicación que usan la instancia de EntityManager dentro de una sola transacción de la API de transacciones de Java (JTA).
Las transacciones JTA usualmente involucran llamadas a través de componentes de aplicaciones. Para completar una transacción JTA, estos componentes generalmente necesitan acceso a un solo contexto de persistencia. Esto ocurre cuando se inyecta un EntityManager en los componentes de la aplicación mediante la anotación javax.persistence.PersistenceContext. El contexto de persistencia se propaga automáticamente con la transacción JTA actual, y las referencias de EntityManager que se asignan a la misma unidad de persistencia brindan acceso al contexto de persistencia dentro de esa transacción. Al propagar automáticamente el contexto de persistencia, los componentes de la aplicación no necesitan pasar las referencias a las instancias de EntityManager entre sí para realizar cambios dentro de una sola transacción. El contenedor Java EE gestiona el ciclo de vida de los gestores de entidades gestionados por contenedor.
Para obtener una instancia de EntityManager, inyecte el administrador de entidades en el componente de la aplicación:
@PersistenceContext EntityManager em;
Gestores de entidades gestionados por la aplicación
Por otro lado, con un administrador de entidades gestionado por la aplicación, el contexto de persistencia no se propaga a los componentes de la aplicación, y la aplicación gestiona el ciclo de vida de las instancias de EntityManager.
Los administradores de entidades administrados por la aplicación se usan cuando las aplicaciones necesitan acceder a un contexto de persistencia que no se propaga con la transacción JTA en las instancias de EntityManager en una unidad de persistencia particular. En este caso, cada EntityManager crea un nuevo contexto de persistencia aislado. El EntityManager y su contexto de persistencia asociado son creados y destruidos explícitamente por la aplicación. También se utilizan cuando no se pueden inyectar directamente instancias de EntityManager porque las instancias de EntityManager no son seguras para subprocesos. Las instancias de EntityManagerFactory son seguras para subprocesos.
Los administradores de entidades no son seguros para subprocesos (fuente de tutorial de Java EE 6 ) y no pueden compartirse entre subprocesos. Cada hilo debe usar su propio administrador de entidades o sucederán cosas malas, independientemente de las llamadas clear()
o close()
.
Pero, si el inyector está inyectando cada hilo con su propio administrador de entidades, entonces las cosas deberían estar bien.
Spring y posiblemente otros marcos de DI inyectarán un proxy basado en ThreadLocal para un administrador de entidad real en sus beans. Las llamadas que hace cada subproceso se dirigirán a la instancia real del subproceso de un administrador de entidades: así es como funcionan las cosas, aunque pueda parecer que un administrador de entidades se comparte entre varios subprocesos.
Más detalles sobre cómo se inyecta a su administrador de entidad ayudarían (Spring, etc.)
Normalmente tiene transacciones en torno a lo que hace con objetos de base de datos. Lo que cada subproceso dado ve sobre los cambios realizados por otros subprocesos está controlado por la configuración de ''aislamiento de transacción''.
Comience a aprender acerca de las diferentes configuraciones de aislamiento y aplique la configuración correcta de acuerdo con sus necesidades. Hay un equilibrio entre la precisión y la velocidad. http://en.wikipedia.org/wiki/Isolation_%28database_systems%29
Aquí está el thread-safe Entity Manager Helper
trabajo thread-safe Entity Manager Helper
.
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
public class EntityManagerHelper {
private static final EntityManagerFactory emf;
private static final ThreadLocal<EntityManager> threadLocal;
static {
emf = Persistence.createEntityManagerFactory("Persistent_Name");
threadLocal = new ThreadLocal<EntityManager>();
}
public static EntityManager getEntityManager() {
EntityManager em = threadLocal.get();
if (em == null) {
em = emf.createEntityManager();
// set your flush mode here
threadLocal.set(em);
}
return em;
}
public static void closeEntityManager() {
EntityManager em = threadLocal.get();
if (em != null) {
em.close();
threadLocal.set(null);
}
}
public static void closeEntityManagerFactory() {
emf.close();
}
public static void beginTransaction() {
getEntityManager().getTransaction().begin();
}
public static void rollback() {
getEntityManager().getTransaction().rollback();
}
public static void commit() {
getEntityManager().getTransaction().commit();
}
}