java - not - ¿Cómo probar si la colección JPA con carga lenta se inicializa?
lazy hibernate example (4)
Tengo un servicio que obtiene una entidad JPA de un código externo. En este servicio me gustaría iterar sobre una colección cargada de forma diferida que es un atributo de esta entidad para ver si el cliente le ha agregado algo en relación con la versión actual en la base de datos.
Sin embargo, es posible que el cliente nunca haya tocado la colección, por lo que aún no se ha inicializado. Esto da como resultado el bien conocido
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.example.SomeEntity.
Por supuesto, si el cliente nunca tocó la colección, mi servicio no tiene que comprobar si hay posibles cambios. La cuestión es que parece que no puedo encontrar una forma de comprobar si la colección está inicializada o no. Creo que podría llamar a size()
y si arroja LazyInitializationException
lo sabría, pero estoy tratando de no depender de esos patrones.
¿Hay algún método isInitialized()
alguna parte?
¿Estás usando JPA2?
PersistenceUnitUtil
tiene dos métodos que se pueden usar para determinar el estado de carga de una entidad.
por ejemplo, existe una relación OneToMany / ManyToOne bidireccional entre Organización y Usuario.
public void test() {
EntityManager em = entityManagerFactory.createEntityManager();
PersistenceUnitUtil unitUtil =
em.getEntityManagerFactory().getPersistenceUnitUtil();
em.getTransaction().begin();
Organization org = em.find(Organization.class, 1);
em.getTransaction().commit();
Assert.assertTrue(unitUtil.isLoaded(org));
// users is a field (Set of User) defined in Organization entity
Assert.assertFalse(unitUtil.isLoaded(org, "users"));
initializeCollection(org.getUsers());
Assert.assertTrue(unitUtil.isLoaded(org, "users"));
for(User user : org.getUsers()) {
Assert.assertTrue(unitUtil.isLoaded(user));
Assert.assertTrue(unitUtil.isLoaded(user.getOrganization()));
}
}
private void initializeCollection(Collection<?> collection) {
// works with Hibernate EM 3.6.1-SNAPSHOT
if(collection == null) {
return;
}
collection.iterator().hasNext();
}
Como indica el otro cartel, Hibernate tiene un método para esto. Sin embargo, no hay una solución para esto en JPA puro.
Para eclipselink
, los usuarios lanzan la colección a la que intenta acceder a org.eclipse.persistence.indirection.IndirectList
, y luego llaman a su método isInstantiated()
. El siguiente enlace tiene más información:
org.hibernate.Hibernate.isInitialized(..)
No hay una solución estándar de JPA que yo sepa. Pero si realmente quiere inicializar colecciones, puede crear un método de utilidad e iterarlas (solo una iteración es suficiente).