Hibernate: не удалось лениво инициализировать коллекцию ролей, ни один сеанс или сеанс не был закрыт - PullRequest
21 голосов
/ 19 августа 2010

Мой код:

    @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 ОШИБКА: org.hibernate.LazyInitializationException не удалось лениво инициализировать коллекцию ролей: xxx.entity.core.User.roleSet, нетсеанс или сеанс закрыты org.hibernate.LazyInitializationException: не удалось лениво инициализировать коллекцию ролей: xxx.entity.core.User.roleSet, ни один сеанс или сеанс не был закрыт в org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException (AbstractPersistentCollection.jpg: 380) at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected (AbstractPersistentCollection.java:372) в org.hibernate.collection.AbstractPersistentCollection.initialize (AbstractPersistentCollection.jcolers PersolS (Java: 212) на sg.com.junglemedia.test.dao.impl.hibernate.UserDaoTest.testAddRoleAndAddUser (UserDaoTest.java:40) в sun.reflect.NativeMethodAccessorImpl.invoke0 (собственный метод) в sun.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:39) в sun.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:25) в java.lang.reflect.Methodj.jj.jj.FrameworkMethod $ 1.runReflectiveCall (FrameworkMethod.java:44) в org.junit.internal.runners.model.ReflectiveCallable.run (ReflectiveCallable.java:15) в org.junit.runners.model.Frameworklykelohololo::.41) в 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) в org.junit.runners.BlockJUnit4ClassRunner.runChild (BlockJUnit4ClassRunner.java:50) в org.junit.junner.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.run (JUnit4TestReference.java:46) в org.eclipse.jdt.internal.junit.runner.TestExecution.run (TestExecution) в org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests (RemoteTestRunner.java:467) в org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests (RemoteTest) orgeclipse.jdt.internal.junit.runner.RemoteTestRunner.run (RemoteTestRunner.java:390) в org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main (RemoteTestRunner.java:197) * 10051007 * Кто-нибудь поможет?

Ответы [ 11 ]

29 голосов
/ 23 октября 2011

В своем классе сущностей, когда вы объявляете отображение от пользователя к роли, попробуйте указать fetchType для EAGER. Примерно так:

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

UPDATE : Последние комментарии, полученные этим ответом, заставляют меня вернуться к этому. Прошло много времени с тех пор, как я ответил, когда я только начал работать с Hibernate. То, что говорят Рафаэль и Мукус, разумно. Если у вас большая коллекция, вы не должны использовать нетерпеливую выборку. Он совместно выбирает все данные, сопоставленные с вашей записью, и загружает в память. Альтернативой этому является использование отложенной выборки и открытие сеанса Hibernate каждый раз, когда вам нужно работать над связанной коллекцией, т.е. каждый раз, когда вам нужно вызвать метод getRoleSet. Таким образом, Hibernate будет выполнять запрос на выборку к базе данных каждый раз, когда вызывается этот метод, и не сохраняет данные коллекции в памяти. Вы можете обратиться к моему сообщению здесь для деталей: http://khuevu.github.io/2013/01/20/understand-hibernate.html

Тем не менее, это может зависеть от вашего фактического варианта использования. Если данные вашей коллекции невелики, и вам часто приходится запрашивать данные, вам будет лучше использовать активную выборку. Я думаю, что в вашем конкретном случае коллекция ролей, вероятно, достаточно мала и подходит для активного поиска.

14 голосов
/ 27 ноября 2013

Вы можете попытаться добавить аннотацию @Transactional к вашему бину или методу (если объявление всех переменных размещается в методе).

4 голосов
/ 04 февраля 2014

У меня возникла та же проблема, поэтому я просто добавил аннотацию @Transactional, откуда я вызывал метод DAO. Это просто работает. Я думаю, что проблема заключалась в том, что Hibernate не позволяет извлекать подобъекты из базы данных, если только не все необходимые объекты во время вызова.

4 голосов
/ 19 августа 2010

Скорее всего, вы закрываете сессию внутри RoleDao.Если вы закроете сеанс, а затем попытаетесь получить доступ к полю объекта, который был загружен с отложенной загрузкой, вы получите это исключение.Вам, вероятно, следует открыть и закрыть сеанс / транзакцию в своем тесте.

3 голосов
/ 08 июня 2015

для меня это сработало так же, как и в eclipselink.Просто вызовите size () коллекции, которую следует загрузить, прежде чем использовать ее в качестве параметра для страниц.

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

Здесь entityListKeeper имеет List of Entity, у которого есть список LazyLoadedEntity.Если у вас есть только что у Entity есть список LazyLoadedEntity, тогда решение будет:

getListLazyLoadedEntity().size();
3 голосов
/ 15 ноября 2010

Следующий код может вызвать похожую ошибку:

  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();
  }
2 голосов
/ 04 июня 2015

У меня была эта проблема, особенно когда сущности запутаны Jaxb + Jax-rs. Я использовал стратегию предварительной выборки, но я также нашел эффективным предоставить две сущности:

  1. Полноценный объект со всеми коллекциями, отображенными как EAGER
  2. Упрощенная сущность с обрезкой большинства или всех коллекций

Общие поля и должны быть отображены в @MappedSuperclass и расширены обеими реализациями сущностей.

Конечно, если вам всегда нужны загруженные коллекции, то нет причин не EAGER загружать их. В моем случае я хотел, чтобы урезанная версия объекта отображалась в сетке.

2 голосов
/ 19 сентября 2013

У вас есть разные варианты, чтобы справиться с этим. Кажется, это возвращает нас к старым добрым обычным дням SQL:)

Читать это: http://www.javacodegeeks.com/2012/07/four-solutions-to-lazyinitializationexc_05.html

1 голос
/ 17 сентября 2017

В моем случае исключение произошло, потому что я удалил "hibernate.enable_lazy_load_no_trans = true" в файле "hibernate.properties" ...

Я сделал копию и вставил опечатку ...

0 голосов
/ 28 декабря 2012

Вы пытаетесь загрузить отложенную загруженную коллекцию, но сеанс гибернации закрыт или недоступен. лучшее решение для этой проблемы, измените загруженный ленивый объект на готовую загрузку fetch = FetchType.EAGER. эта проблема решит.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...