代码之家  ›  专栏  ›  技术社区  ›  LunaticJape

Spring boot@Async注解抛出LazyInitializationException

  •  1
  • LunaticJape  · 技术社区  · 8 年前

    我有一个emailsenderservice来异步管理电子邮件通知。

    @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 回复  |  直到 8 年前
        1
  •  3
  •   Ernesto Campohermoso    8 年前

    你对JPA有意见。

    您可以查看以下内容的详细说明: Difference between FetchType LAZY and EAGER in Java Persistence API?

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

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

    延迟加载铅的更好技术:

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