Весенняя загрузка @Async-аннотация сгенерировать LazyInitializationException - PullRequest
0 голосов
/ 26 сентября 2018

У меня есть emailsenderservice для асинхронного управления уведомлениями по электронной почте.Есть 2 асинхронных метода, один метод работает, а другой выдает LazyInitializationException:

@Service
public class EmailSenderService {
    // working
    @Async
    public void sendNewBidRequestEmail(BidRequest bidRequest) {
        this.sendNewBidRequestEmailToSupplier(bidRequest);
    }
    @Transactional
    public void sendNewBidRequestEmailToSupplier(BidRequest bidRequest) {
        sendNewBidRequestEmailToSupplier(bidRequest, bidRequest.getHotels());
    }

    @Transactional
    public void sendNewBidRequestEmailToSupplier(BidRequest bidRequest, List<Hotel> hotelList) {
        for (Hotel hotel : hotelList) {
           ...
           this.sender.send()
        }
    }


    // not working, throw exception
    @Async
    public void sendCancelledBidRequestEmail(BidRequest bidRequest, String reason) {
        this.sendCancelledBidRequestEmailToSupplier(bidRequest, bidRequest.getHotels(), reason);
    }

    @Transactional
    public void sendCancelledBidRequestEmailToSupplier(BidRequest bidRequest, List<Hotel> hotelList, String reason) {
        for (Hotel hotel : hotelList) {   // throw exception here
           ...
           this.sender.send();
        }
}

Я полностью слежу за этой темой .Вы можете видеть, что оба асинхронных метода имеют почти одинаковую структуру.Асинхронный метод вызывает транзакционный метод.Но второй бросает org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.corpobids.server.entity.BidRequest.hotels, could not initialize proxy - no Session.

Я даже имитирую структуру первого асинхронного метода, чтобы изменить второй:

@Async
    public void sendCancelledBidRequestEmail(BidRequest bidRequest, String reason) {
        this.sendCancelledBidRequestEmailToSupplier(bidRequest, reason);
    }

    @Transactional
    public void sendCancelledBidRequestEmailToSupplier(BidRequest bidRequest, String reason) {
        this.sendCancelledBidRequestEmailToSupplier(bidRequest, bidRequest.getHotels(), reason);
    }

    @Transactional
    public void sendCancelledBidRequestEmailToSupplier(BidRequest bidRequest, List<Hotel> hotelList, String reason) {
        for (Hotel hotel : hotelList) {   // exception in this line
               ...
               this.sender.send();
            }
    }
}

На этот раз он дает мне java.lang.IllegalStateException: org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl@fce9b7b is closed.

Я хотел бы знать, что пропущено в моем коде, любая помощь будет признательна.

1 Ответ

0 голосов
/ 26 сентября 2018

У вас проблемы с JPA.

В JPA отношения OneToMany имеют два поведения: LAZY и EAGER.

Вы можете проверить хорошее объяснение: Разница между FetchType LAZY и EAGERв Java Persistence API?

Я предполагаю, что когда вы вызываете свой код в асинхронном режиме, контекст JPA теряется.Таким образом, Hibernate не может заполнить отношения, выполняя новый запрос, поскольку контекст другой.Чтобы решить вашу проблему, у вас есть два варианта:

  1. Сконфигурировать отношения с EAGER
  2. Предварительно загрузить отношения перед вызовом асинхронного метода

Лучшие методы дляпривести с Ленивой Загрузка:

https://www.thoughts -on-java.org / 5-способы-инициализировать-ленивые-отношения-и-когда-использовать-их /

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