Сессия Hibernate в фоновом потоке всегда закрывается, вызывая LazyInitializationException - PullRequest
0 голосов
/ 04 октября 2018

Я пытаюсь выполнить некоторую работу по чтению, вычислению и сохранению JPA в фоновом потоке, запущенном методом сервиса.Я делаю всю свою работу в одном методе @Transactional сервиса.Другой метод в этой службе запускает поток, который его обрабатывает.Однако, если я пытаюсь получить доступ к ленивым отношениям @oneToMany, даже если я делаю это сразу же после получения результатов в первый раз, я получаю LazyInitializationException - без сеанса.Как не может быть никакого сеанса?Я ПРОСТО ПОЛУЧИЛ РЕЗУЛЬТАТ ОДНОЙ ЛИНИИ ДО.

Пожалуйста, игнорируйте, что пул потоков здесь не используется.Этот код написан на Groovy, поэтому разработчикам, работающим только на Java, может быть сложно понять.

@Service
public class NotifierService {
public void startNewNotifierThread() {
    stopNotifierThreadIfRunning()
    log.info "Starting notifier thread"

    notifierThread = new Thread({
        while(!Thread.interrupted()) {
            runNotifier()
            Thread.sleep(10000)
        }

        if(Thread.interrupted()) {
            log.info("Reached end of thread due to interrupt")
        }
    })

    notifierThread.start()
}

@Transactional public void runNotifier() {
    boolean isAlive0 = TransactionSynchronizationManager.isActualTransactionActive()
    Session session = (Session) entityManager.getDelegate();
    Collection<User> allSubscribedUsers = userRepository.getAllSubscribedUsers()

    log.debug "Processing subscriptions for ${allSubscribedUsers.size()} subscribed users"

    int fcmMsgsSent = 0, apnMsgsSent = 0
    boolean isAlive1 = TransactionSynchronizationManager.isActualTransactionActive()

    allSubscribedUsers.each { User user ->
        boolean isAlive2 = TransactionSynchronizationManager.isActualTransactionActive()
        log.debug "Subscriptions for user ${user.email}: ${user.analysisSubscriptions.size()}"

        Set<AnalysisSubscription> updatedSubscriptions = new HashSet<AnalysisSubscription>()

        user.analysisSubscriptions.each { AnalysisSubscription subscription ->
            boolean isAlive3 = TransactionSynchronizationManager.isActualTransactionActive()

            int numResults = subscription.analysisResults.size() //LAZYINITIALIZATIONEXCEPTION
        }
    }
}

Результатом этого кода является isAlive0, isAlive1, isAlive2, isAlive3 - все false.Значение session.closed равно true даже в начале метода, который не имеет смысла, почему он может извлечь всех подписанных пользователей (если я использую репозиторий внизу - что заставляет меня подозревать, что метод использует свой собственный сеанс ...)?).Кажется, что @Transactional не работает: он должен ОТКРЫТЬ сеанс гибернации и ПРОДОЛЖИТЬ ОТКРЫТЬ до конца метода.Кажется, он даже не открывает сессию.

1 Ответ

0 голосов
/ 04 октября 2018

Это хорошая статья о том, как управление транзакциями в Spring работает с несколькими потоками.Это похоже на ваш пример.

Дело в том, что вы не можете запустить новый поток (), поскольку Transaction относится к локальным значениям потока, которые присутствуют только в текущем потоке.

Вероятно, вам следует загрузить ленивые ссылки, прежде чем покинуть допустимый поток или определить @Async @Transactional Службы

https://dzone.com/articles/spring-transaction-management-over-multiple-thread-1

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