有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java Spring boot@Async注释引发LazyInitializationException异常

我有一个emailsenderservice来异步管理电子邮件通知。 有两种异步方法,一种方法有效,但另一种方法引发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) 个答案

  1. # 1 楼答案

    你对JPA有意见

    在JPA中,夫妻关系有两种行为:懒惰和渴望

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

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

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

    针对延迟加载的lead的更好技术:

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