Java Hibernate:未能延迟初始化角色集合,没有会话或会话被关闭

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3519059/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 01:28:36  来源:igfitidea点击:

Hibernate: failed to lazily initialize a collection of role, no session or session was closed

javahibernate

提问by Ben

My code:

我的代码:

    @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)

13:39:41,041 错误:org.hibernate.LazyInitializationException 未能延迟初始化角色集合:xxx.entity.core.User.roleSet,没有会话或会话被关闭 org.hibernate.LazyInitializationException:未能延迟初始化集合角色:xxx.entity.core.User.roleSet,没有会话或会话在 org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:380) 处关闭,在 org.hibernate.collection.AbstractPersistentCollection.throwIfLazyInitialization() 372) 在 org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:365) 在 org.hibernate.collection.PersistentSet.add(PersistentSet.java:212) 在 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.DelegatingMethod 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) 在 org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28) 在 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) 在 org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191) 在 org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)在 org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184) 在 org.junit.runners.ParentRunner.run(ParentRunner.java:236) 在 org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference。在 org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) 在 org.eclipse.jdt.internal.junit.runner.RemoteTestRunner 运行(JUnit4TestReference.java:46)。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.run) java:390) 在 org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

Anyone help?

有人帮忙吗?

回答by Javid Jamae

You're most likely closing the session inside of the RoleDao. If you close the session then try to access a field on an object that was lazy-loaded, you will get this exception. You should probably open and close the session/transaction in your test.

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

回答by jiang peng

The following code can cause similar error:

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

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

You can fix it simply:

您可以简单地修复它:

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

回答by Khue Vu

In your entity class, when you declare mapping from user to roles, try specifying the fetchType to EAGER. Some thing like this:

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

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

UPDATE: Recent comments this answer's received make me revisit this. It's been a while since I answered, when I only started working with Hibernate. What Rafael and Mukus say are reasonable. If you have a large collection, you shouldn't use eager fetching. It jointly selects all data mapped to your entry and loads to memory. An alternative to this is to still use lazy fetching and open a Hibernate session each time you need to work on the related collection, i.e, each time you need to invoke getRoleSet method. This way, Hibernate will execute the select query to database each time this method is invoked and doesn't keep the collection data in memory. You can refer to my post here for details: http://khuevu.github.io/2013/01/20/understand-hibernate.html

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

That's said, it can depend on your actual use case. If your collection data is small and you frequently need to query the data, you will better off using eager fetching. I think, in your specific case, a collection of role is probably quite small and suitable to use eager fetching.

也就是说,这取决于您的实际用例。如果您的集合数据很小并且您经常需要查询数据,那么最好使用 Eager fetching。我认为,在您的特定情况下,角色集合可能很小并且适合使用热切获取。

回答by priya

Your trying to load the lazy loaded collection, but the hibernate session is closed or unavailable. the best solution for this problem, change the lazy loaded object to eager fetch = FetchType.EAGER loading. this problem will solve.

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

回答by bkomac

You have different choices to handle this. It seem like its taking us back to old good plain SQL days :)

你有不同的选择来处理这个问题。似乎它把我们带回了过去的好纯 SQL 时代:)

Read this: http://www.javacodegeeks.com/2012/07/four-solutions-to-lazyinitializationexc_05.html

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

回答by DraggonZ

You can try to add @Transactional annotation to your bean or method (if declaration of all variables places in method).

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

回答by Athar

I was experiencing the same issue so just added the @Transactional annotation from where I was calling the DAO method. It just works. I think the problem was Hibernate doesn't allow to retrieve sub-objects from the database unless specifically all the required objects at the time of calling.

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

回答by Jason Holmberg

I've had this issue especially when entities are mashalled by Jaxb + Jax-rs. I've used the pre-fetch strategy, but I have also found it effective to provide two entities:

我遇到了这个问题,尤其是当实体被 Jaxb + Jax-rs 混搭时。我使用了预取策略,但我也发现提供两个实体是有效的:

  1. Full-blown entity with all collections mapped as EAGER
  2. Simplified entity with most or all collections trimmed out
  1. 完整的实体,所有集合都映射为 EAGER
  2. 删除了大部分或所有集合的简化实体

Common fields and be mapped in @MappedSuperclassand extended by both entity implementations.

公共字段@MappedSuperclass并由两个实体实现映射和扩展。

Certainly if you always need the collections loaded, then there is no reason to not to EAGERload them. In my case I wanted a stripped down version of the entity to display in a grid.

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

回答by makkasi

for me it worked the approach that I used in eclipselink as well. Just call the size() of the collection that should be loaded before using it as parameter to pages.

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

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

Here entityListKeeper has List of Entity that has list of LazyLoadedEntity. If you have just therelation Entity has list of LazyLoadedEntity then the solution is:

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

getListLazyLoadedEntity().size();

回答by Laura Liparulo

In my case the Exception occurred because I had removed the "hibernate.enable_lazy_load_no_trans=true" in the "hibernate.properties" file...

就我而言,发生异常是因为我删除了“hibernate.properties”文件中的“hibernate.enable_lazy_load_no_trans=true”...

I had made a copy and paste typo...

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