java - example - Hibernación: no se pudo inicializar perezosamente una colección de roles, no se cerró ninguna sesión o sesión
hibernate spring (11)
Mi código:
@Test
public void testAddRoleAndAddUser() {
Role r = roleDao.findByProperty("name", "admin");
if(r == null) {
r = new Role();
r.setName("admin");
r.setDescription("Just administrator.");
roleDao.save(r);
}
User u = dao.get(1l);
Set<Role> roles = u.getRoleSet();
logger.debug("Roles is null: " + (roles == null));
roles.add(r);
dao.save(u);
}
13: 39: 41,041 ERROR: org.hibernate.LazyInitializationException no pudo iniciar perezosamente una colección de roles: xxx.entity.core.User.roleSet, ninguna sesión o sesión se cerró org.hibernate.LazyInitializationException: no se pudo inicializar perezosamente una colección de función: xxx.entity.core.User.roleSet no se cerró la sesión en la naturaleza. 372) en org.hibernate.collection.AbstractPersistentCollection.initialize (AbstractPersistentCollection.java:365) en org.hibernate.collection.PersistentSet.add.ta.p. .UserDaoTest.testAddRoleAndAddUser (UserDaoTest.java:40) en sun.reflect.NativeMethodAccessorImpl.invoke0 (Método nativo) en sun.reflect.NativeMethodAccessorImpl.invoke (NativeMet) hodAccessorImpl.java:39) en sun.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:25) en java.lang.reflect.Munhod.Puniv.Pun.P. runReflectiveCall (FrameworkMethod.java:44) en org.junit.internal.runners.model.ReflectiveCallable.run (ReflectiveCallable.java:15) en org.junit.runners.model.FrameworkMethod.invokeExplosively (FrameworkMethod.junners.jpg) .junit.internal.runners.statements.InvokeMethod.evaluate (InvokeMethod.java:20) en org.junit.internal.runners.statements.RunBefores.evaluateJPPPPPPPPPPPPPJPPPJPPPPPPPPPPPJPPJPJPPJPPJPPJPJPPPPPPPPPPPNP (BlockJUnit4ClassRunner.java:76) en org.junit.runners.BlockJUnit4ClassRunner.runChild (BlockJUnit4ClassRunner.java:50) en org.junit.runners.ParentRunner $ 3.run (ParentRunner.j. Programación de $ 1. (ParentRunner.java:52) en org.junit.runners.ParentRunner.runChildren (ParentRunner.java:191) en org.junit.runners.ParentRunner.acce ss $ 000 (ParentRunner.java:42) en org.junit.runners.ParentRunner $ 2.evaluate (ParentRunner.java:184) en org.junit.runners.ParentRunner.run (ParentRunner.java:236) en org.eclipse.jdt .internal.junit4.runner.JUnit4TestReference.run (JUnit4TestReference.java:46) en la org.eclipse.jdt.internal.junit.runner.Tun.pest. .runner.RemoteTestRunner.runTests (RemoteTestRunner.java:467) en org.eclipse.jdt.internal.junit.runner.Remote. .run (RemoteTestRunner.java:390) en org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main (RemoteTestRunner.java:197)
Alguien ayuda?
El siguiente código puede causar un error similar:
using (var session = SessionFactory.OpenSession())
using (var tx = session.BeginTransaction())
{
movie = session.Get<Movie>(movieId);
tx.Commit();
}
Assert.That(movie.Actors.Count == 1);
Puedes arreglarlo simplemente:
using (var session = SessionFactory.OpenSession())
using (var tx = session.BeginTransaction())
{
movie = session.Get<Movie>(movieId);
Assert.That(movie.Actors.Count == 1);
tx.Commit();
}
En mi caso, la Excepción ocurrió porque eliminé "hibernate.enable_lazy_load_no_trans = true" en el archivo "hibernate.properties" ...
Había hecho una copia y pegar error tipográfico ...
En su clase de entidad, cuando declara la asignación de usuario a roles, intente especificar fetchType a EAGER. Algo como esto:
@OneToMany(fetch=FetchType.EAGER)
public Collection<Role> getRoleSet(){
...
}
ACTUALIZACIÓN : Los comentarios recientes recibidos de esta respuesta me hacen volver a esto. Ha pasado un tiempo desde que respondí, cuando solo comencé a trabajar con Hibernate. Lo que dicen Rafael y Mukus son razonables. Si tiene una colección grande, no debe usar la búsqueda ansiosa. Selecciona conjuntamente todos los datos asignados a su entrada y se carga en la memoria. Una alternativa a esto es seguir usando la recuperación perezosa y abrir una sesión de Hibernate cada vez que necesite trabajar en la recopilación relacionada, es decir, cada vez que necesite invocar el método getRoleSet. De esta manera, Hibernate ejecutará la consulta de selección a la base de datos cada vez que se invoque este método y no mantenga los datos de la colección en la memoria. Puede consultar mi publicación aquí para obtener más información: http://khuevu.github.io/2013/01/20/understand-hibernate.html
Dicho esto, puede depender de su caso de uso real. Si los datos de su colección son pequeños y necesita consultarlos con frecuencia, será mejor que utilice una búsqueda ansiosa. Creo que, en su caso específico, es probable que una colección de roles sea bastante pequeña y adecuada para utilizar la búsqueda ansiosa.
Está intentando cargar la colección cargada de forma perezosa, pero la sesión de hibernación está cerrada o no está disponible. la mejor solución para este problema, cambie el objeto cargado perezoso a eager fetch = FetchType.EAGER loading. Este problema lo resolverá.
Estaba experimentando el mismo problema, así que acabo de agregar la anotación @Transactional desde donde estaba llamando el método DAO. Simplemente funciona. Creo que el problema fue que Hibernate no permite recuperar subobjetos de la base de datos a menos que específicamente todos los objetos requeridos al momento de la llamada.
He tenido este problema, especialmente cuando las entidades son combinadas por Jaxb + Jax-rs. He utilizado la estrategia de búsqueda previa, pero también me ha resultado eficaz proporcionar dos entidades:
- Entidad en toda regla con todas las colecciones asignadas como
EAGER
- Entidad simplificada con la mayoría o todas las colecciones recortadas
Los campos comunes y se asignan en @MappedSuperclass
y se extienden por las implementaciones de ambas entidades.
Ciertamente, si siempre necesita que las colecciones se carguen, entonces no hay razón para no EAGER
en EAGER
. En mi caso, quería una versión reducida de la entidad para mostrar en una cuadrícula.
Lo más probable es que cierres la sesión dentro del RoleDao. Si cierra la sesión y luego intenta acceder a un campo en un objeto cargado de forma perezosa, obtendrá esta excepción. Probablemente debería abrir y cerrar la sesión / transacción en su prueba.
Para mí funcionó el enfoque que utilicé también en eclipselink. Simplemente llame al tamaño () de la colección que debe cargarse antes de usarlo como parámetro para las páginas.
for (Entity e : entityListKeeper.getEntityList()) {
e.getListLazyLoadedEntity().size();
}
Aquí entityListKeeper tiene una lista de entidades que tiene una lista de LazyLoadedEntity. Si tiene una entidad de la lista de LazyLoadedEntity, la solución es:
getListLazyLoadedEntity().size();
Puede intentar agregar la anotación @Transactional a su bean o método (si la declaración de todas las variables se coloca en el método).
Revisa esta publicación de blog en español que puedes traducir. También tiene algunas referencias a otra documentación.
Tienes diferentes opciones para manejar esto. Parece que nos está devolviendo a viejos buenos tiempos de SQL llano :)
Lea esto: http://www.javacodegeeks.com/2012/07/four-solutions-to-lazyinitializationexc_05.html