Hibernate:懒得初始化一个角色集合,没有会话或会话被关闭

我的代码:

@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 roles = u.getRoleSet(); logger.debug("Roles is null: " + (roles == null)); roles.add(r); dao.save(u); } 

13:39:41,041错误:org.hibernate.LazyInitializationException无法懒惰地初始化角色集合:xxx.entity.core.User.roleSet,没有会话或会话被关闭org.hibernate.LazyInitializationException:懒得初始化一个集合role:xxx.entity.core.User.roleSet,org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:380)org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:)中没有关闭任何会话或会话。 372)atg.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(NativeMet) hodAccessorImpl.java:39)在org.junit.runners.model.FrameworkMethod $ 1的java.lang.reflect.Method.invoke(Method.java:597)的sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)。 org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)上的orRe.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)中的runReflectiveCall(FrameworkMethod.java:44)位于org.junit.runners.BlockJUnit4ClassRunner.runChild的org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)中的.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20) (BlockJUnit4ClassRunner.java:76)org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)org.junit.runners.ParentRunner $ 3.run(ParentRunner.java:193)org.junit.runners.ParentRunner $ 1.schedule(ParentRunner.java:52)org.junit.runner.runChildner.ParentRunner.ac 位于org.eclipse.jdt的org.junit.runners.ParentRunner $ 2.evaluate(ParentRunner.java:184)org.junit.runners.ParentRunner.run(ParentRunner.java:236)的ss $ 000(ParentRunner.java:42) .internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46)位于org.eclipse.jdt.internal.junit的org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) .runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)atg.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)org.eclipse.jdt.internal.junit.runner.RemoteTestRunner .run(RemoteTestRunner.java:390)at or.e.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

有人帮吗?

在您的实体类中,当您声明从用户到角色的映射时,请尝试将fetchType指定为EAGER。 有点像这样:

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

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

这就是说,它可能取决于您的实际用例。 如果您的收集数据很小并且您经常需要查询数据,那么最好使用急切提取。 我认为,在您的具体情况下,角色的集合可能非常小并且适合使用渴望获取。

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

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

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

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

你可以简单地解决它:

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

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

对我而言,它也适用于我在eclipselink中使用的方法。 在将其用作页面参数之前,只需调用应加载的集合的size()。

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

这里entityListKeeper具有包含LazyLoadedEntity列表的实体列表。 如果您刚刚有实体,那么实体有LazyLoadedEntity列表,那么解决方案是:

 getListLazyLoadedEntity().size(); 

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

你有不同的选择来处理这个问题。 它似乎把它带回了旧的好的纯SQL日:)

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

我有这个问题,特别是当实体被Jaxb + Jax-rs编组时。 我已经使用了预取策略,但我发现提供两个实体也很有效:

  1. 完整的实体,所有集合都映射为EAGER
  2. 修剪掉大部分或全部集合的简化实体

公共字段并在@MappedSuperclass进行映射,并由两个实体实现进行扩展。

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

在我的情况下发生exception是因为我删除了“hibernate.properties”文件中的“hibernate.enable_lazy_load_no_trans = true”…

我做了一个复制并粘贴拼写错误…

查看您可以翻译的西class牙语博客文章 。 它还有一些对另一个文档的引用。