休眠:未能初始化懒洋洋角色的集合,没有会话或会话关闭

休眠:未能初始化懒洋洋角色的集合,没有会话或会话关闭

问题描述:

我的代码:休眠:未能初始化懒洋洋角色的集合,没有会话或会话关闭

@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 failed to lazily initialize a collection of role: xxx.entity.core.User.roleSet, no session or session was closed org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: xxx.entity.core.User.roleSet, no session or session was closed at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:380) at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:372) at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:365) at org.hibernate.collection.PersistentSet.add(PersistentSet.java:212) at sg.com.junglemedia.test.dao.impl.hibernate.UserDaoTest.testAddRoleAndAddUser(UserDaoTest.java:40) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20) at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:76) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184) at org.junit.runners.ParentRunner.run(ParentRunner.java:236) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

谁能帮助?

+0

什么'保存(你)'做?你如何管理'Session'?你打开/关闭它在哪里? – 2010-08-19 08:21:02

您很可能会关闭RoleDao中的会话。如果关闭会话,然后尝试访问延迟加载对象上的字段,则会得到此异常。您可能应该在测试中打开和关闭会话/事务。

用西班牙文检查this blog post您可以翻译。它也有一些对另一个文档的引用。

下面的代码可能会导致类似的错误:

using (var session = SessionFactory.OpenSession()) 
    using (var tx = session.BeginTransaction()) 
    { 
     movie = session.Get<Movie>(movieId); 
     tx.Commit(); 
    } 
    Assert.That(movie.Actors.Count == 1); 

你可以简单地解决这个问题:

using (var session = SessionFactory.OpenSession()) 
    using (var tx = session.BeginTransaction()) 
    { 
     movie = session.Get<Movie>(movieId); 
     Assert.That(movie.Actors.Count == 1); 
     tx.Commit(); 
    } 

在你的实体类,当你从用户声明映射到角色,尝试指定fetchType到EAGER。有些事情是这样的:

@OneToMany(fetch=FetchType.EAGER) 
public Collection<Role> getRoleSet(){ 
... 
} 

UPDATE: 最新评论这个答案的获得让我重温这一点。从我回答开始,只有我开始使用Hibernate的时候已经有一段时间了。拉斐尔和穆库斯说的是合理的。如果你有一个很大的集合,你不应该使用预先抓取。它共同选择映射到您的条目的所有数据并加载到内存中。另一种方法是每次需要处理相关的集合时,仍然使用延迟获取并打开一个Hibernate会话,即每次需要调用getRoleSet方法时。这样,每次调用此方法时,Hibernate都会对数据库执行select查询,并且不会将收集数据保留在内存中。你可以参考我的帖子在这里的详细信息:http://khuevu.github.io/2013/01/20/understand-hibernate.html

这就是说,它可以取决于您的实际使用情况。如果您的收集数据很小并且您经常需要查询数据,那么最好使用预先抓取。我认为,就你的具体情况而言,角色集合可能非常小,适合使用预先抓取。

+0

我面临一个类似的问题,通过映射具有多对多的集合(并且未指定获取类型)。我得到了LazyInitializationException,但是当我更改为提取类型Eager时,它正常工作。在提取类型Lazy中是否有任何错误? – vvekselva 2012-08-24 08:52:15

+1

@vvekselva,你可以参考这个问题:http://*.com/questions/2990799/difference-between-fetchtype-lazy-and-eager-in-java-persistence – 2012-08-26 01:46:28

+37

这不是一个解决方案,而是一个解决方法 – Rafael 2013-12-13 12:50:15

您试图加载延迟加载的集合,但休眠会话已关闭或不可用。 解决此问题的最佳解决方案,将延迟加载的对象更改为eget fetch = FetchType.EAGER加载。这个问题将解决。

+19

这不是一个解决方案,而是一个解决方法 – Marc 2013-06-12 15:54:02

你有不同的选择来处理这个问题。它看起来像它带我们回到老好普通的SQL天:)

阅读:http://www.javacodegeeks.com/2012/07/four-solutions-to-lazyinitializationexc_05.html

你可以尝试@Transactional注释添加到您的bean或方法(如果方法中所有变量的地方声明) 。

+0

进入这个确切的错误,并意识到我需要一个@Transactional注释(对于我的Spring测试环境),如上所述。 – 8bitme 2014-10-13 12:12:28

我遇到同样的问题,所以只是从我调用DAO方法的地方添加@Transactional注释。它只是工作。我认为问题是Hibernate不允许从数据库中检索子对象,除非在调用时特别需要所有必需的对象。

我有这个问题,特别是当实体被Jaxb + Jax-rs控制时。我用预取策略,但我也觉得这有效地提供两个实体:

  1. 与映射为EAGER所有集合
  2. 大多数或所有集合
  3. 简化实体修剪出全面爆发的实体

常见字段和映射在@MappedSuperclass并且由两个实体实现扩展。

当然,如果你总是需要加载的集合,那么没有理由不去EAGER加载它们。在我的情况下,我想要一个精简版本的实体显示在网格中。

对我来说,它的工作方式,我用eclipselink以及。只需调用应该加载的集合的size(),然后再将其用作页面的参数。

for (Entity e : entityListKeeper.getEntityList()) { 
    e.getListLazyLoadedEntity().size(); 
} 

这里entityListKeeper具有实体的名单有LazyLoadedEntity的名单。 如果刚therelation实体LazyLoadedEntity的名单,然后解决方法是:在“hibernate.properties”因为我已经删除了 “hibernate.enable_lazy_load_no_trans =真”发生

getListLazyLoadedEntity().size(); 

在我的情况异常文件...

我做了一个复制和粘贴错字...