Hibernate(8)之延迟加载

Hibernate(8)之延迟加载

微信搜索 zze_coding 或扫描 👉 二维码关注我的微信公众号获取更多资源推送:

概述

延迟加载,也叫懒加载。当我们使用 session.load() 方法来加载一个对象时,此时并不会发出 SQL 语句,当前得到的这个对象其实是一个代理对象,这个代理对象只保存了实体对象的 id 值,只有当我们要使用这个对象,得到其它属性时,这个时候才会发出 SQL 语句,从数据库中去查询我们的对象。

类级别的延迟加载

介绍

指的是查询某个类的对象时,针对这个类的对象是否使用延迟加载。

除了修改 lazy="false" 这种方式,还可通过如下两种方式让 lazy 失效:

  1. 将持久化类以 final 修饰。
  2. 通过调用 Hibernate.initialize(proxy); 。

示例

懒加载

修改映射文件:

<!-- com/zze/bean/Class.hbm.xml -->
<class name="com.zze.bean.Class" table="class" lazy="true">
<!-- lazy 默认为 true -->
Session session = HibernateUtil.getCurrentSession();
Transaction transaction = session.beginTransaction();
Class clazz = session.load(Class.class, 1);
System.out.println(clazz.getClass()); // class com.zze.bean.Class_$$_jvst718_0
System.out.println(clazz); // 发出 SQL
transaction.commit();

立即加载

修改映射文件:

<!-- com/zze/bean/Class.hbm.xml -->
<class name="com.zze.bean.Class" table="class" lazy="false">
Session session = HibernateUtil.getCurrentSession();
Transaction transaction = session.beginTransaction();
Class clazz = session.load(Class.class, 1); // 发出 SQL
System.out.println(clazz.getClass()); // class com.zze.bean.Class
System.out.println(clazz);
transaction.commit();

关联级别的延迟加载

介绍

指的是查询到某个对象后,再查询其关联的对象是否使用延迟加载。

示例

一对多懒加载

修改映射文件:

<!-- com/zze/bean/Class.hbm.xml -->
<set name="students" cascade="save-update" lazy="true">
<!-- lazy 默认为 true -->
Session session = HibernateUtil.getCurrentSession();
Transaction transaction = session.beginTransaction();
Class clazz = session.get(Class.class, 1);
Set<Student> students = clazz.getStudents();
System.out.println(students); // 发出 SQL
transaction.commit();

多对一懒加载

修改映射文件:

<!-- com/zze/bean/Student.hbm.xml -->
<many-to-one name="clazz" lazy="proxy" column="cid" class="com.zze.bean.Class"/>
<!-- proxy 为默认值,表示引用关联类的加载策略。-->
<!-- com/zze/bean/Class.hbm.xml -->
<class name="com.zze.bean.Class" table="class" lazy="true">
Session session = HibernateUtil.getCurrentSession();
Transaction transaction = session.beginTransaction();
Student student = session.get(Student.class, 1);
Class clazz = student.getClazz();
System.out.println(clazz); // 发出 SQL
transaction.commit();

一对多即时加载

修改映射文件:

<!-- com/zze/bean/Class.hbm.xml -->
<set name="students" cascade="save-update" lazy="false">
Session session = HibernateUtil.getCurrentSession();
Transaction transaction = session.beginTransaction();
Class clazz = session.get(Class.class, 1);
Set<Student> students = clazz.getStudents(); // 发出 SQL
System.out.println(students);
transaction.commit();

多对一即时加载

当关联类的 lazy="false" 时,无论当前类 many-to-one 标签上的 lazy 如何配置,都是即时加载。

修改映射文件,以下方式二选一:

<!-- com/zze/bean/Student.hbm.xml -->
<many-to-one name="clazz" lazy="proxy" column="cid" class="com.zze.bean.Class"/>
<!-- com/zze/bean/Class.hbm.xml -->
<class name="com.zze.bean.Class" table="class" lazy="false">

<!-- com/zze/bean/Student.hbm.xml -->
<many-to-one name="clazz" lazy="false" column="cid" class="com.zze.bean.Class"/>
<class name="com.zze.bean.Class" table="class" lazy="true">
Session session = HibernateUtil.getCurrentSession();
Transaction transaction = session.beginTransaction();
Student student = session.get(Student.class, 1);
Class clazz = student.getClazz(); // 发出 SQL
System.out.println(clazz);
transaction.commit();

Copyright: 采用 知识共享署名4.0 国际许可协议进行许可

Links: https://www.zze.xyz/archives/hibernate8.html

Buy me a cup of coffee ☕.