2012-11-08 3 views
0

Я читаю некоторые объекты с Hibernate:LazyInitializationException при доступе к коллекции в Runnable

Criteria criteria = session.createCriteria(…); 
List<Entity> list = (List<Entity>) criteria.list(); 

Теперь я итерация этого списка и хочу отправить каждый объект внутри Runnable к Executor. Поэтому я использую RunnableBean.

for (Entity entity : list) { 
    IRunnableBean runnableBean = (IRunnableBean) 
     applicationContext.getBean("myRunnableBean", IRunnableBean.class); 
    runnableBean.setEntity(entity); 
    executor.execute(runnableBean); 
} 

RunnableBean выглядит следующим образом:

RunnableBean implements IRunnableBean { 

    // Setter 

    @Transactional 
    void run() { 
     entity.getMyCollection(); 
    } 
} 

Когда я получить доступ к коллекции, я получаю org.hibernate.LazyInitializationException (no session or session was closed).

В журнале Spring я вижу, что транзакционный метод run() правильно добавлен. Что я делаю не так?

ответ

2

Я думаю, вы используете Spring's OpenSessionInViewFilter. Если это так, ожидается такое поведение. Фильтр помещает соединение с базой данных в локальный контекст потока, который недоступен в вашем RunnableBean.

Поскольку myCollection не загружается должным образом, Spring не имеет доступа к соединению с базой данных: RunnableBean и не может его загрузить. Вам необходимо:

  • создайте закрывающую сессионную обертку в RunnableBean;
  • передать идентификатор вашей коллекции в RunnableBean вместо передачи объекта и загрузить коллекцию в RunnableBean

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

0

Просто добавьте следующую строку в вашем уже написанных for цикла:

Hibernate.initialize(entity.getMyCollection()); 

Это не загрузит коллекцию жадно вместо лениво: нет LazyInitializationException больше.

0

Я бы также предположил (например, @mindas), что транзакция недоступна в вашем компоненте, потому что она работает в другом потоке, чем транзакция, которая содержит транзакцию. Что касается моего опыта, то весна также использует локаторы потоков для разрешения доверенных прокси-серверов, поэтому они не будут работать ни в компоненте, который запускается асинхронно.

В принципе, я попытался бы избежать запуска логики, требующей транзакции в асинхронном режиме, поскольку асинхронные вызовы выполняются в течение более длительного времени (в противном случае зачем использовать асинхронные вызовы?), И это заблокирует транзакцию и/или приведет к таймаутам ,

Критерии api из jpa предлагают способы получения отношения с нетерпением только для конкретного запроса. Может быть, это может быть выбор? В противном случае доступ к методу size() коллекции будет инициализировать его.

Смежные вопросы