项目运行过程中,一个报错信息,报错信息如下:

org.hibernate.LazyInitializationException: could not initialize proxy [xxx.domain.Guild#CF12263C600F4BCABC9293D3FABE4B42] - no Session
at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:169) ~[hibernate-core-5.3.9.Final.jar!/:5.3.9.Final]
at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:309) ~[hibernate-core-5.3.9.Final.jar!/:5.3.9.Final]
at org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor.intercept(ByteBuddyInterceptor.java:45) ~[hibernate-core-5.3.9.Final.jar!/:5.3.9.Final]
at org.hibernate.proxy.ProxyConfiguration$InterceptorDispatcher.intercept(ProxyConfiguration.java:95) ~[hibernate-core-5.3.9.Final.jar!/:5.3.9.Final]
at xxx.domain.Guild$HibernateProxy$58NSae2j.getName(Unknown Source) ~[classes!/:0.0.9-SNAPSHOT]
at xxx.task.TaskJiaoFuService.guildName(TaskJiaoFuService.java:181) ~[classes!/:0.0.9-SNAPSHOT]
at xxx.task.TaskJiaoFuService.result2JiaoFuDetail(TaskJiaoFuService.java:122) ~[classes!/:0.0.9-SNAPSHOT]
at xxx.task.TaskJiaoFuService.parseResult(TaskJiaoFuService.java:106) ~[classes!/:0.0.9-SNAPSHOT]
at xxx.task.TaskJiaoFuService.queryV4(TaskJiaoFuService.java:91) ~[classes!/:0.0.9-SNAPSHOT]
at xxx.AbstractExportStrategy.query(AbstractExportStrategy.java:65) ~[classes!/:0.0.9-SNAPSHOT]
at xxx.ExportService.exportAndPersistence(ExportService.java:130) [classes!/:0.0.9-SNAPSHOT]
at xxx.ExportService.lambda$execute$0(ExportService.java:75) [classes!/:0.0.9-SNAPSHOT]
at xxx.common.initialization.ContextCopyingTaskDecorator.lambda$decorate$0(ContextCopyingTaskDecorator.java:20) ~[classes!/:0.0.9-SNAPSHOT]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[na:1.8.0_181]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[na:1.8.0_181]
at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_181]

业务很简单,一个jpa的单表查询,获取属性的时候报错了

分析

JPA默认使用的懒加载,即使访问的是单个实体类,返回的对象也是代理,在获取对象属性的时候才会进行数据库查询,此时如果连接数据session已释放则会抛出上述异常

org.hibernate.LazyInitializationException在经常使用hibernate或者jpa的同学中可能经常遇到,网络上一搜,解决问题的方式有很多种,这里罗列一下:

  • 在spring boot的配置文件application.properties添加spring.jpa.open-in-view=true
  • 用spring 的OpenSessionInViewFilter
  • 在spring boot的配置文件application.properties添加spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true
  • 在出问题的实体类上加@Proxy(lazy = false)
  • ……

spring.jpa.open-in-view

我们看下baeldung上是怎么说的,传送门:https://www.baeldung.com/spring-open-session-in-view

Session per request is a transactional pattern to tie the persistence session and request life-cycles together. Not surprisingly, Spring comes with its own implementation of this pattern, named OpenSessionInViewInterceptor, to facilitate working with lazy associations and therefore, improving developer productivity.

………

By default, OSIV is active in Spring Boot applications. Despite that, as of Spring Boot 2.0, it warns us of the fact that it's enabled at application startup if we haven't configured it explicitly:

spring.jpa.open-in-view is enabled by default. Therefore, database
queries may be performed during view rendering.Explicitly configure
spring.jpa.open-in-view to disable this warning

意思大致是,每个请求会话对于Spring来说都是一种事务模式,所以了我们默认给你开启了,用于提高开发效率,不过你如果没有显式配置的话,我还会给你一个warning告警。关于这个默认配置在github上争论也有不少:https://github.com/spring-projects/spring-boot/issues/7107

OSIV时序图如下:

项目中spring.jpa.open-in-view是设置为false的,代码获取实体类或者关联实体都是service中完成的,一般我们开启事务,在事务作用的上下文环境中去获取懒加载的数据是不会有任何问题的,且开启之后数据的session会等到整个request完成之后才会释放,其实是十分消耗性能的,之前有其他同学没有关闭open-in-view遇到的问题:https://www.cnblogs.com/thisismarc/p/13594399.html

结论:spring.jpa.open-in-view为true可以解决报错,不过不推荐,OpenSessionInViewFilter配置方案也PASS

spring.jpa.properties.hibernate.enable_lazy_load_no_trans

我们也看下baeldung上是怎么说的,传送门:https://www.baeldung.com/hibernate-lazy-loading-workaround

While using lazy loading in Hibernate, we might face exceptions, saying there is no session.

……

The recommended approach is to design our application to ensure that data retrieval happens in a single transaction. But, this can sometimes be difficult when using a lazy entity in another part of the code that is unable to determine what has or hasn't been loaded.

Hibernate has a workaround, an enable_lazy_load_no_trans property. Turning this on means that each fetch of a lazy entity will open a temporary session and run inside a separate transaction.

意思大致是,这是一种变通的做法,可以为每个懒加载的实体打开一个临时的会话,不过这个方法也是反人类的,因为如果延迟加载的关联实体越多,请求附加的连接也就越多,这会给数据库连接带来压力。在新事务中加载的每个关联,在每次关联初始化后都会强制刷新事务日志,所以大大的不建议使用。

@Proxy(lazy = false)

@Proxy(lazy = false)的意思和FetchType.EAGER类似,返回的是初始化好的实体,即关闭了懒加载,这个肯定不是我们想要的

推荐解决方式

回到我们的问题,单表懒加载报错,项目使用的是Springboot,事务都是显式的注解配置,查询的接口我们一般没有配置@Transactional注解,所以解决方法是在Service的查询方法上增加 @Transactional(readOnly = true) 注解来划分事务边界,这是比较推荐的做法,也复合编码规范,项目中如果有事务切面配置,把相关方法加到事务控制的范围中则也不会出现这个问题,如果还有其他更好的方式,欢迎留言

参考链接

https://vladmihalcea.com/the-hibernate-enable_lazy_load_no_trans-anti-pattern/

https://www.baeldung.com/spring-open-session-in-view

https://github.com/spring-projects/spring-boot/issues/7107

https://www.cnblogs.com/thisismarc/p/13594399.html

https://www.baeldung.com/hibernate-lazy-loading-workaround

解决org.hibernate.LazyInitializationException的正确姿势的更多相关文章

  1. 【bug记录】jpa 解决org.hibernate.lazyinitializationexception could not initialize proxy - no session

    前言 最近开发项目比较忙,Spring Cloud的笔记得稍稍放放了,下午出来个bug,恶心的不行,功能很简单,也没有什么级联或复杂的映射关系,就是一直在报三个异常 Caused by: com.fa ...

  2. 解决org.hibernate.LazyInitializationException: could not initialize proxy - no Session懒载入问题

    问题描写叙述: Struts Problem Report Struts has detected an unhandled exception: Messages: could not initia ...

  3. jpa 解决org.hibernate.lazyinitializationexception could not initialize proxy - no session

    org.hibernate.LazyInitializationException: could not initialize proxy [org.alan.entity.SysUser#1] - ...

  4. 剖析和解决Python中网络粘包的正确姿势

    目录 1.粘包及其成因 1.1.粘包产生 1.2.粘包产生的原因 2.尝试解决粘包 2.1.指定数据包的长度 2.2.固定数据包的长度 2.3.用函数实现多次调用发送数据 3.解决粘包问题的正确姿势 ...

  5. dubbo序列化hibernate.LazyInitializationException could not initialize proxy - no Session懒加载异常的解决

    dubbo序列化,hibernate.LazyInitializationException could not initialize proxy - no Session懒加载异常的解决 转载声明: ...

  6. 总结懒加载的解决方法(全)org.hibernate.LazyInitializationException: could not initialize proxy - no Session

    如下错误:org.hibernate.LazyInitializationException: could not initialize proxy - no Session 原因是懒加载的问题,因为 ...

  7. Ubuntu 解决wifi无法打开的问题 安装NVIDIA显卡驱动的正确姿势

    游戏本型号Y7000 win10 Ubuntu16.04双系统 解决wifi无法打开的问题 解决方法: 1.打开终端输入:rfkill list all 出现如下提示::       可以看到,优先级 ...

  8. org.hibernate.LazyInitializationException异常解决办法

    org.hibernate.LazyInitializationException异常failed to lazily initialize a collection...的解决方案使用hiberna ...

  9. 在Linux(ubuntu server)上面安装NodeJS的正确姿势

    上一篇文章,我介绍了 在Windows中安装NodeJS的正确姿势,这一篇,我们继续来看一下在Linux上面安装和配置NodeJS. 为了保持一致,这里也列举三个方法 第一个方法:通过官网下载安装 h ...

随机推荐

  1. 感知机与支持向量机 (SVM)

    感知机与SVM一样都是使用超平面对空间线性可分的向量进行分类,不同的是:感知机的目标是尽可能将所有样本分类正确,这种策略指导下得出的超平面可能有无数个,然而SVM不仅需要将样本分类正确,还需要最大化最 ...

  2. 熬夜总结vue3中setUp函数的2个参数详解

    1.setUp函数的第1个参数props setup(props,context){} 第一个参数props: props是一个对象,包含父组件传递给子组件的所有数据. 在子组件中使用props进行接 ...

  3. 20204107 孙嘉临《PYTHON程序设计》计算器设计实验二报告

    课程:<python程序设计> 班级:2041 姓名:孙嘉临 学号:20204107 实验教师:王志强 实验日期:2021年4月12日 必修/选修:公选课 ##一.实验内容 设计并完成一个 ...

  4. JWT原理实现代码

    JWT学习文章: 第一篇:JWT原理 第二篇:JWT原理实现代码 上一篇学习了JWT的基本理论,这一篇将根据原理进行代码实现. 要想实现jwt的加密解密,要先生成一个SecurityKey,大家可以在 ...

  5. Java并发之ReentrantLock源码解析(四)

    Condition 在上一章中,我们大概了解了Condition的使用,下面我们来看看Condition再juc的实现.juc下Condition本质上是一个接口,它只定义了这个接口的使用方式,具体的 ...

  6. vue中$nextTick详细讲解保证你一看就明白

    1.功能描述 今天我们要实现这个一个小功能: 页面渲染完成后展示一个div元素: 当点击这个div元素后: div元素消失: 出现一个input元素:并且input元素聚焦 想必大家我觉得简单,我们一 ...

  7. kubelet分析-pvc扩容源码分析

    kubernetes ceph-csi分析目录导航 存储的扩容分为controller端操作与node端操作两大步骤,controller端操作由external-resizer来调用ceph完成,而 ...

  8. 41、解决du与df统计不一致的解决方法

    41.1.案例说明: 通过df -hT和du -sh /.du -h --max-depth=1 /命令 发现磁盘的使用不量不一致,使用'df -hT'命令查看磁盘的使用量要 比使用'du -sh / ...

  9. elk 日志收集 filebeat 集群搭建 php业务服务日志 nginx日志 json 7.12版本 ELK 解决方案

    难的不是技术,难的是业务.熟悉业务流程才是最难的. 其实搜索进来的每一个人的需求不一样,希望你能从我的这篇文章里面收获到. 建议还是看官方文档,更全面一些. 一.背景 1,收集nginx  acces ...

  10. Linux Netfilter框架分析

    目录 Netfilter框架 Netfilter的5个hook点 netfilter协议栈数据流分析 连接跟踪conntrack conntrack连接跟踪表条目 连接跟踪表大小 管理连接跟踪表 ip ...