Hibernate中的抓取策略优化

本文详细介绍了Hibernate中延迟加载的概念,包括类级别和关联级别的延迟加载,并深入探讨了抓取策略的配置方法,如fetch和lazy属性的设置,以及批量抓取的优化策略。
Hibernate中的类加载

1、什么是延迟加载?

延迟加载:lazy(懒加载)。执行到该行代码的时候,不会发送语句去进行查询,在真正使用这个对象的属性的时候才会发送SQL语句进行查询。


2、延迟加载的分类

(1)类级别的延迟加载
(2)关联级别的延迟加载


3、类级别延迟加载

(1)类级别的延迟加载

指的是通过load方法查询某个对象的时候,是否采用延迟。
session.load(Emp.class, 1001);

(2)类级别的延迟加载怎么配置?

类级别延迟加载,通过该类映射文件中的标签里的属性lazy进行配置为true。当然默认就是true,不配置也行。

(3)延迟加载失效情况有哪些?

  • lazy默认值是true,如果设置为false,类级别延迟加载会失效。
  • 如果持久化类使用final修饰,也会导致类级别延迟加载失效。
  • Hibernate. initialize(obj)方法也会取消延迟加载,执行到这行代码会立马发送查询语句。

4、关联级别的延迟加载

(1)指的是在查询到某个对象的时候,查询其关联的对象的时候,是否采用延迟加载。

Dept dept= session.get(Dept.class, 10);
dept.getEmps();

// 通过部门获得员工的时候,员工对象是否采用了延迟加载,称为是关联级别的延迟。

(2)如何配置关联级别的延迟加载

关联级别延迟加载,通过该类映射文件中的或者标签里的属性lazy进行配置。

抓取策略往往会和关联级别的延迟加载一起使用,优化语句。



Hibernate中的抓取策略

1、什么是抓取策略?

通过一个对象抓取到关联对象需要发送SQL语句,SQL语句如何发送,发送成什么样格式通过策略进行配置。


2、怎么配置抓取策略?

通过<set>或者<many-to-one>中的fetch, lazy属性进行设置。

fetch 和 lazy如何设置,达到优化SQL语句?


3、<set>上的fetch 和 lazy配置

fetch:抓取策略,控制SQL语句格式
lazy:延迟加载,控制查询关联对象的时候是否采用延迟

(1)<set>中fetch的属性值有:

  • select :默认值,发送普通的select语句,查询关联对象
  • join :发送一条迫切左外连接查询关联对象。
  • subselect :发送一条子查询查询其关联对象。

(2)<set>中lazy的属性值有:

  • true :默认值,查询关联对象的时候,采用延迟加载。
  • false :查询关联对象的时候,不采用延迟加载。
  • extra :及其懒惰,在代码上使用什么,它就查询什么,没有多余的。

注意:
当fetch配置join值时,lazy值失效
因为join是迫切左外连接,一次性已经查询了关联的对象。
总共有7种搭配。常用默认或者join。

在实际开发中,一般都采用默认值。
如果有特殊的需求,可能需要配置fetch属性为join值。


4、<many-to-one>上的fetch 和 lazy配置

fetch :抓取策略,控制SQL语句格式。
lazy :延迟加载,控制查询关联对象的时候是否采用延迟。

(1)<many-to-one>中fetch的属性值有:

  • select :默认值,发送普通的select语句,查询关联对象。
  • join :发送一条迫切左外连接。

(2)<many-to-one>中lazy的属性值有:

  • proxy :默认值,proxy具体的取值,取决于另一端的上的lazy的值。
  • false :查询关联对象,不采用延迟。
  • no-proxy :(不会使用)

在实际开发中,也一般都采用默认值。
如果有特殊的需求,可能需要配置fetch属性为join值。


5、批量抓取

什么是批量抓取?

查询多个对象,其关联对象一起抓取,也叫batch-size。
例如:查询多个部门,及其关联的员工信息。

一对多关系中配置batch-size:
在一的一方映射文件中,set标签上配置batch-size属性。
在多的一方映射文件中,class标签上配置batch-size属性。
属性值默认是1,需要设置其他值。

这个值设置的为x,与数据库交互的select次数为:(N / x) + 1。
并不是越大越好,假如数据量特别大,值也设置很大,一次性加载很多数据,对于内存消耗过大。
一般设置为50。具体看需求的数据量。


如果没有配置的情况下:
查询所有部门,及其关联的员工信息。
假设有5个部门,会发送5+1条select语句,效率很低。

如果在部门映射文件set标签中配置了batch-size值为3:
则会发送(5 / 3) + 1,发送3条select语句,效率提高。

测试代码:

package com.pipi.hibernate05;

import com.pipi.hibernate04.Dept;
import com.pipi.hibernate04.Emp;
import myutils.HibernateUtil;
import org.hibernate.Session;
import org.hibernate.Transaction;

import java.util.List;

// 测试批量抓取:bitch-size
public class Test_batch_size {
    public static void main(String[] args) {

        Session session = HibernateUtil.getCurrentSession();
        Transaction transaction = session.beginTransaction();

        // 查询所有部门Dept,批量查询关联的员工Emp(dept表中有5行数据)
        // 在Dept.hbm.xml中的<set>标签中配置batch-size值为3,将会发送几条select语句?   3条
        String hql = "from Dept";
        List<Dept> depts = session.createQuery(hql).list();
        for (Dept d : depts) {
            System.out.println(d);
            for (Emp e : d.getEmps()) {
                System.out.println(e);
            }
        }

        session.clear();  // 清空session缓存的数据,以便影响下面的测试数据
        System.out.println("-----------------------------------------------------------");

        // 查询所有员工Emp,批量查询关联的部门Dept(emp表中有14行数据)
        // 在Emp.hbm.xml中的<class>标签中配置batch-size值为5,将会发送几条select语句?   4条
        String hql2 = "from Emp";
        List<Emp> emps = session.createQuery(hql2).list();
        for (Emp e : emps) {
            System.out.println(e);
            System.out.println(e.getDept());
        }

        transaction.commit();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值