Hibernate Session Threading - PullRequest
       0

Hibernate Session Threading

5 голосов
/ 20 марта 2011

У меня проблема с Hibernate и отложенной загрузкой.

Справочная информация: у меня есть веб-приложение Spring MVC, я использую Hibernate для своего слоя персистентности.Я использую OpenSessionInViewFilter, чтобы позволить мне лениво загружать объекты в моем слое представления.И я расширяю классы HibernateDaoSupport и использую HibernateTemplate для сохранения / загрузки объектов.Все работало довольно хорошо.До сих пор.

Проблема: у меня есть задача, которую можно запустить с помощью веб-запроса.Когда запрос направляется на контроллер, контроллер создаст новый Runnable для этой задачи и запустит поток для запуска задачи.Таким образом, оригинальный поток вернется, и сеанс Hibernate, который был помещен в ThreadLocal (OpenSessionInViewFilter), не будет доступен новому потоку для Задачи.Поэтому, когда задача выполняет какие-то действия с базой данных, я получаю печально известную исключительную ситуацию LazyInitializationException.

Может ли кто-нибудь предложить лучший способ сделать сеанс Hibernate доступным для задачи?

Спасибо за чтение.

Ответы [ 3 ]

5 голосов
/ 20 марта 2011

Сделайте ваш Runnable Spring bean и добавьте @Transactional аннотацию над run.Вы должны быть предупреждены, что эта асинхронная задача не будет выполняться в той же транзакции, что и ваш веб-запрос.

И, пожалуйста, не запускайте новый поток, используйте пул / executor.

1 голос
/ 13 июля 2015

Вот рабочий пример того, как использовать сеанс Hibernate внутри Runnable:

@Service
@Transactional
public class ScheduleService {

    @Autowired
    private SessionFactory      sessionFactory;

    @Autowired
    private ThreadPoolTaskScheduler     scheduler;

    public void doSomething() {

        ScheduledFuture sf = scheduler.schedule(new Runnable() {
            @Override
            public void run() {
                SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(scheduler);
                final Session session = sessionFactory.openSession();
                // Now you can use the session
            }
        }, new CronTrigger("25 8 * * * *"));
    }
}

SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext() принимает ссылку на любой управляемый компонент Spring, поэтому с планировщиком все в порядке. Любой другой боб, управляемый Spring, также подойдет.

0 голосов
/ 20 марта 2011

Правильно ли я понимаю, вы хотите выполнить какое-то действие в полностью выделенном фоновом потоке, верно? В этом случае я рекомендую вам вообще не обращаться к Hibernates OpenSessionInViewFilter и к дальнейшей логике сеанса для этого потока, потому что, как вы правильно заметили, он будет выполняться в отделенном потоке и, следовательно, в информации, загруженной в исходный поток (т. Е. Тот, который разобрался с начальным HttpRequest). Я думаю, что было бы разумно открыть и закрыть сеанс самостоятельно в этой теме.

В противном случае вы можете спросить, почему вы выполняете эту операцию в отдельном потоке. Может быть, этого достаточно, чтобы нормально запустить операцию и подарить пользователю какой-нибудь экран «загрузки»?

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