如何解决JPA延迟加载no Session报错

异常展示

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: ****, could not initialize proxy - no Session
    at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:582)
    at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:201)
    at org.hibernate.collection.internal.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:145)
    at org.hibernate.collection.internal.PersistentBag.size(PersistentBag.java:261)

问题原因

触发延迟加载的时候,session已经失效

延迟加载原理

通过cglib对目标Entity实现代理,针对配置了延迟加载的属性,修改对应get方法的逻辑,植入延迟加载逻辑

解决方式

  1. 不使用延迟加载
  2. 延迟加载的时候session活跃

我们本来就想使用延迟加载来提高性能的,不使用延迟加载只是你逃避问题的方式!!要用延迟加载的地方必须用它!!

如何让延迟加载时session活跃

web项目

在springboot环境下,打开以下配置即可

spring.jpa.open-in-view=true

这个配置会通过WebMvcConfigurer配置一个OpenEntityManagerInViewInterceptor拦截器

而这个拦截器的作用。。我们看他的注释就知道了

就是处理请求的全程都能获取到EntityManager,其实就是能获取到session的意思。

普通提供dubbo服务的项目

在接口方法上加上@Transactional注解即可。

@Override
@Transactional(rollbackFor = Exception.class)
public List getAllXX() {
    List result = xXQueryRepository.findAll();
    return XXConverter.INSTANCE.entityListToDTOList(result);
}

@Transactional会保证在所注解方法作用域内session都生效

你可能感兴趣的:(如何解决JPA延迟加载no Session报错)