• JPA 中 LazyInitializationException 解决方案


    JPA 中使用关系注解例如@ManyToOne@OneToMany ,其中fetchType参数默认为 LAZY 对象懒加载 ;当关联实体类在数据库没有记录存在时,会报出LazyInitializationException 错误:

    org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.cn.entity.test.GroupClass.students, could not initialize proxy - no Session

    错误出现原因 ,简单来说就是,以延迟方式加载对象时,此时 Hibernate 与数据库通信时 session 已经管理了,没有相关 session 可以通信了。

    深入理解错误之前,需要了解 sessionLazy initialisation 以及 Proxy Object 等基本概念,以及在 Hibernate 框架中它们是怎么一起运作的

    • 1,session 代表一个持久化 上下文,对应用和数据库之间代表一种通信交流,类似于客户端与服务器之间的通信 session (会话)
    • 2,懒加载意味对象不会直接从 session context 加载,触发条件是从代码层获取的时候才会加载。
    • 3,Hibernate 创建一个 动态 Proxy Object 类作为代理来访问数据库,并且仅当我们首次使用对象时,它才访问数据库;

    LazyInitializationException 错误发生是当我们尝试借助代理对象从数据库中获取一个懒加载对象,但 Hibernate session 此时已经关闭,从而报错

    该错误解决方法:

    方法一,修改配置

    在配置文件 ymlproperties 中将 hibernate.enable_lazy_load_no_trans 参数设为 true,该参数 用于声懒加载对象的的获取全局方式,默认为 false ,打开它意味着当每次以懒加载方式获取关联实体对象时,都将运行在新的事务中的新会话中。

     spring:
      jpa:
        # 控制台打印 sql
        show-sql: false
        hibernate:
          ddl-auto: none
        properties:
          # 解决 LazyInitializationException 错误
          hibernate.enable_lazy_load_no_trans: true
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    方法存在一定的弊端:会导致 N+1 问题,Hibernate 首先执行一个 Select 来获取 目标实体类,然后根据实体类关联的属性,再执行 N(N 代表关联属性的个数 ) 个 Select 操作查询实体类的相关属性;

    方法二,修改关联注解中 FetchType

    FetchType.LAZY 更改为 FetchType.EARLY ,当我们需要用到关联类的大多数级联属性时,这算一种较为常规的修改方法

    @OneToMany(mappedBy = "groupClass",cascade = CascadeType.ALL,fetch = FetchType.EAGER)
    @OrderBy("name DESC")
    private List<Student> students = new ArrayList<>();
    
    • 1
    • 2
    • 3
    方法三,利用 Hibernate Criteria API 方法
    Criteria criteria = session.createCriteria(GroupClass.class);
    criteria.setFetchMode("students", FetchMode.EAGER);
    
    • 1
    • 2

    对比以上方法,该方法是最高效的,查询时通过一条 SQL 语句实现从数据库中获取目标实体关联集合,解决N+1Select 查询效率问题

  • 相关阅读:
    Linux实验操作二
    Bigder:40/100 怎么组织一次用例评审
    架构设计(高可用)
    Map和Set
    练习7-在Verilog中使用任务task
    Spring Boot整合日志
    JVM完整图文学习笔记 (含拓展知识广度学习) 第三章: 类加载与字节码技术
    技术分享 | 抓包分析 TCP 协议
    淘客APP开发定制系统推荐
    Ubuntu22.04桌面版的 mkdir , mkdir -p 命令笔记2221107
  • 原文地址:https://blog.csdn.net/weixin_42512684/article/details/128058585