Spring Boot @Async批注抛出LazyInitializationException

时间:2018-09-26 13:43:11

标签: java spring hibernate

我有一个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();
        }
}

我完全关注this thread。 您可以看到两种异步方法的结构几乎相同。异步方法调用事务方法。但是第二个抛出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 :(得分:1)

您在使用JPA时遇到问题。

在JPA中,关系OneToMany具有两种行为LAZY和EAGER。

您可以在以下位置查看正确的解释:Difference between FetchType LAZY and EAGER in Java Persistence API?

我假设在异步模式下调用代码时,JPA的上下文是松散的。由于上下文不同,因此Hibernate无法填充执行新查询的关系。为了解决您的问题,您有两种选择:

  1. 配置与EAGER的关系
  2. 在调用异步方法之前预加载关系

延迟加载的更好铅技术:

https://www.thoughts-on-java.org/5-ways-to-initialize-lazy-relations-and-when-to-use-them/