Hibernate:没有延迟初始化一个角色集合,没有关闭会话或会话。

时间:2022-12-21 17:29:08

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,没有会话或会话是关闭的。hibernate。LazyInitializationException:没有延迟地初始化一个角色集合:xxx.entity.core.User。roleSet,没有会话或会话在org.hibernate. collection.abstractpersistentcollection.java:380)在org.hibernate. collection.abstractpersistentcollection.java372 . abstractpersistentcollection .initialize(AbstractPersistentCollection.java: 372)在org. hibernates. abstractpersistentcollection.(AbstractPersistentCollection.java:365)。在sun.reflect.NativeMethodAccessorImpl sg.com.junglemedia.test.dao.impl.hibernate.UserDaoTest.testAddRoleAndAddUser(UserDaoTest.java:40)。在sun.reflect.nativemethodaccessor.调用(nativemethodaccessor. java:39)在sun.reflec . delegatingmethodaccessorrequest .invoke(委托methodaccessor. java:25)在java. junit. .invoke(方法.java:597)。(java:20) . . . . . . . . . . . . . ., . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ., . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .第二部分,第二部分,第二部分,第二部分,第二部分,第二部分,第二部分,第二部分,第二部分,第二部分,第二部分,第二部分,第一部分,第二部分,第二部分,第二部分,第二部分,第二部分,第二部分,第二部分,第二部分,第二部分,第二部分,第二部分,第二部分,第二部分,第二部分,第二部分,第二部分,第二部分,第二部分,第二部分,第二部分,第二部分,第二部分,第一部分,第一部分。< / span > < span style = ' font - size: 9.0 pt; font - family:宋体;mso - ascii - font - family: tahoma; mso - hansi - font - family: calibri;

Anyone help?

有人帮助吗?

11 个解决方案

#1


27  

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的时候。拉斐尔和穆克斯说的是合理的。如果你有一个大的收藏,你不应该使用急切取回。它联合选择映射到您的条目的所有数据并加载到内存中。另一种方法是,每次需要在相关集合上工作时,仍然使用惰性抓取并打开Hibernate会话。每次您需要调用getRoleSet方法。通过这种方式,Hibernate将在每次调用此方法时执行select查询,而不会将收集数据保存在内存中。你可以参考我在这里的帖子,了解详情:http://khuevu.github. io/2013/01/20/- 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.

这就是说,它可以依赖于你的实际用例。如果您的收集数据很小,并且您经常需要查询数据,那么您将更好地使用热切抓取。我认为,在您的特定案例中,一个角色的集合可能非常小,并且适合使用热切的抓取。

#2


10  

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

您可以尝试向您的bean或方法添加@Transactional注释(如果在方法中声明了所有变量的位置)。

#3


4  

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中的会话。如果关闭会话,然后尝试访问被延迟加载的对象上的字段,就会得到这个异常。您应该在测试中打开并关闭会话/事务。

#4


3  

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();
  }

#5


3  

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不允许从数据库中检索子对象,除非在调用时特别指定所有必需的对象。

#6


3  

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中使用的方法。只需调用在将其作为参数使用到页面之前应该加载的集合的大小()。

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();

#7


2  

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.

您试图加载延迟加载的集合,但是hibernate会话是关闭的或不可用的。对于这个问题,最好的解决方案是将延迟加载的对象更改为eager fetch = FetchType。立即加载。这个问题会解决。

#8


2  

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

#9


2  

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. 包含所有集合的成熟实体映射为热切。
  3. Simplified entity with most or all collections trimmed out
  4. 简化的实体,大部分或全部集合被裁剪掉。

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

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

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

当然,如果您总是需要装载集合,那么就没有理由不急于加载它们。在我的例子中,我想要一个精简版的实体在网格中显示。

#10


0  

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

在我的情况下,异常发生是因为我删除了“hibernate”。enable_lazy_load_no_trans = true”在“冬眠。属性“文件…

I had made a copy and paste typo...

我做了一个复制和粘贴排版…

#11


-1  

Check this blog post in spanish which you can translate. It also has some references to another documentation.

看看这个你可以翻译的西班牙语博客。它还对另一个文档有一些引用。

#1


27  

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的时候。拉斐尔和穆克斯说的是合理的。如果你有一个大的收藏,你不应该使用急切取回。它联合选择映射到您的条目的所有数据并加载到内存中。另一种方法是,每次需要在相关集合上工作时,仍然使用惰性抓取并打开Hibernate会话。每次您需要调用getRoleSet方法。通过这种方式,Hibernate将在每次调用此方法时执行select查询,而不会将收集数据保存在内存中。你可以参考我在这里的帖子,了解详情:http://khuevu.github. io/2013/01/20/- 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.

这就是说,它可以依赖于你的实际用例。如果您的收集数据很小,并且您经常需要查询数据,那么您将更好地使用热切抓取。我认为,在您的特定案例中,一个角色的集合可能非常小,并且适合使用热切的抓取。

#2


10  

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

您可以尝试向您的bean或方法添加@Transactional注释(如果在方法中声明了所有变量的位置)。

#3


4  

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中的会话。如果关闭会话,然后尝试访问被延迟加载的对象上的字段,就会得到这个异常。您应该在测试中打开并关闭会话/事务。

#4


3  

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();
  }

#5


3  

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不允许从数据库中检索子对象,除非在调用时特别指定所有必需的对象。

#6


3  

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中使用的方法。只需调用在将其作为参数使用到页面之前应该加载的集合的大小()。

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();

#7


2  

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.

您试图加载延迟加载的集合,但是hibernate会话是关闭的或不可用的。对于这个问题,最好的解决方案是将延迟加载的对象更改为eager fetch = FetchType。立即加载。这个问题会解决。

#8


2  

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

#9


2  

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. 包含所有集合的成熟实体映射为热切。
  3. Simplified entity with most or all collections trimmed out
  4. 简化的实体,大部分或全部集合被裁剪掉。

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

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

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

当然,如果您总是需要装载集合,那么就没有理由不急于加载它们。在我的例子中,我想要一个精简版的实体在网格中显示。

#10


0  

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

在我的情况下,异常发生是因为我删除了“hibernate”。enable_lazy_load_no_trans = true”在“冬眠。属性“文件…

I had made a copy and paste typo...

我做了一个复制和粘贴排版…

#11


-1  

Check this blog post in spanish which you can translate. It also has some references to another documentation.

看看这个你可以翻译的西班牙语博客。它还对另一个文档有一些引用。