Как работать с фоновыми потоками в приложении Hibernate / Spring - PullRequest
3 голосов
/ 16 июня 2011

Я спрашиваю, как мне справляться с фоновыми потоками, выполняющими задачи, связанные с базой данных, в моем веб-приложении Hibernate / Spring.

В настоящее время я использую следующий перехватчик, поэтому я могу аннотировать методы запуска потока с помощью @OpenSession, и сессия должна быть открыта. Это также должно работать, например, для запросов RMI или любого другого метода, который вызывается без открытия сеанса. Однако я не уверен, что код правильный, но я сталкиваюсь с проблемой, что иногда сессии просто не закрываются и остаются открытыми навсегда.

@Around("@annotation(openSession)")
    public Object processAround(ProceedingJoinPoint pjp, OpenSession openSession) throws Throwable {

        boolean boundResource = false;
        Session session = null;

        // Bind the session to the thread, if not already done
        if(TransactionSynchronizationManager.getResource(sessionFactory) == null) {
            log.debug("Opening Hibernate Session in method "+pjp.getSignature());

            session = SessionFactoryUtils.getSession(sessionFactory, true);
            TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session));
            boundResource = true;
        }

        // Invoke the annotated method
        Object ret;
        try {
            ret = pjp.proceed();
        }
        catch(Throwable t) {
            // Rethrows the Exception but makes sure the session will be closed
            SessionFactoryUtils.closeSession(session);
            log.debug("Closing Hibernate Session in method (Exception thrown) "+pjp.getSignature());
            throw t;
        }

        // If a resourc was bound by this method call, unbind it.
        if(boundResource) {
            //SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.unbindResource(sessionFactory);
            session.flush();
            SessionFactoryUtils.closeSession(session);

            log.debug("Closing Hibernate Session in method "+pjp.getSignature());
        }

        return ret;
    }

Ответы [ 2 ]

1 голос
/ 16 июня 2011

Да, предложенное вами решение должно работать (я сам сделал нечто очень похожее). Если вы используете только @Transactional, вы получите новый EntityManager для каждой транзакции, что не всегда оптимально, если в фоновом потоке много транзакций.

1 голос
/ 16 июня 2011

Сеансы Hibernate и соединения JDBC не являются потокобезопасными.Вы должны придерживаться соединения и сеанса на поток.

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