Hibernate中的加载策略

本文介绍了Hibernate中的加载策略,包括类级别和关联级别的加载策略。详细讨论了一对多关系中的lazy和fetch属性组合,如何影响数据加载行为,如是否使用懒加载、是否进行表连接查询等。还涉及了在many-to-one标签中的加载策略设置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


前言

这一篇主要记录了Hibernate中的加载策略,通过在xml中的不同配置,我们可以设置不同的加载策略。加载策略一般分为延迟加载和立即加载,延迟加载是在使用的时候才会加载数据,立即加载是不管使用不使用,都会立刻加载数据。


一、两种级别的加载策略

加载策略分为类级别加载策略和关联级别加载策略。
类级别加载策略比较简单,最常见的列子就是,load和get这两个方法。在Hibernate学习笔记-环境配置以及常用对象这篇中有介绍过这两种方法的区别,get方法其实就是立即加载,它会立即查询数据库,将数据初始化。而load方法,在默认的设置下(在class标签中,lazy默认值为true),是一个延迟加载,它会返回一个代理对象,使用代理对象的属性时,才去查数据库;如果把lazy的值设置为false,那么load将会和get方法一样。
对于load的lazy属性的设置实例如下:

<hibernate-mapping package="com.hibern.pojo">
	<!--在class标签中加上lazy属性-->
    <class name="Customer" table="t_customer" lazy="false">
        <id name="id" column="id">
            <generator class="native"></generator>
        </id>
        <property name="name" column="name" type="string"></property>
        <set name="orders">
            <key column="cid"></key>
            <one-to-many class="Order"/>
        </set>
    </class>
</hibernate-mapping>

关联级别的加载一般用于一对多关系中,这里要注意的是,我们可以在一的关系那一边设置加载策略,也可以在多的关系那一边设置加载策略。

二、关联级别的加载策略(一对多)

1. lazy属性和fetch属性

下面的列子以从客户表找订单为案例,来看下加载策略的几种情况(这里加载策略的属性主要配置在set标签内的)。

<hibernate-mapping package="com.hibern.pojo">
    <class name="Customer" table="t_customer" lazy="false">
        <id name="id" column="id">
            <generator class="native"></generator>
        </id>
        <property name="name" column="name" type="string"></property>
        <!--set中有两个属性和加载有关,分别是lazy和fetch,这里没有填写具体的值,每个值代表什么意思下面的内容会具体分析-->
        <set name="orders" lazy="xxx" fetch="xxx">
            <key column="cid"></key>
            <one-to-many class="Order"/>
        </set>
    </class>
</hibernate-mapping>
  • lazy:是否对set数据使用懒加载
    true:默认值,对集合使用懒加载(在查询用户表的时候,不会查询该用户关联的订单,只有通过用户对象去获取订单对象的时候才会查询订单表)
    false:集合会被立刻加载(情况就与上面相反)

    (上面的截图是设置为false的情况,通过断点可以看到,当执行完15行的时候,此时打印的sql语句有两条,分别是查询了用户信息和用户的订单信息)
    extra:极其懒惰(如果要获取某一用户的订单个数,即使用customer.getOrders().size(),不会查询订单的数据,只会用count去获取数量)
    在这里插入图片描述
    (这里可以看到,但我们执行完16行代码的时候,打印的语句是一条用count去查询的订单数量的sql;如果我们把extra改成true的话,这里将会打印查询订单完整信息的sql。)
  • fetch:决定加载集合使用的sql语句种类
    select:默认值,普通select语句查询
    join:表链接语句查询集合数据(此时查询的sql语句会是连接两个表的查询语句)
    在这里插入图片描述
    (在这里可以看到,同样的代码,当我们设置了fetch=join之后,打印的sql语句是一条连接查询的语句。)
    subselect:使用子查询加载集合数据
    在这里插入图片描述
    (这里需要说明的是,子查询是要先查询出所有的用户,再遍历用户的时候,获取对应用户的订单信息的时候才能看到这样的效果。下面组合情况会具体展示示例代码。)
2. lazy属性和fetch属性的组合情况

在这里插入图片描述
lazy=true fetch=select:在使用集合的时候(执行第二行)才加载(每执行一行,分别打印对应的sql语句–查询用户数据和订单数据)
lazy=true fetch=join:查询用户表数据的时候就直接打印一条连接查询的sql语句(执行第一行,就会打印sql,且只打印这一条)
lazy=false fetch=select:查询用户数据的时候,就打印用户表的查询和订单表的查询的sql语句(执行第一行,直接打印两条select查询语句)
lazy=false fetch=join:查询用户表数据的时候就直接打印一条连接查询的sql语句(执行第一行,就会打印sql,且只打印这一条)
lazy=extra fetch=select:查询用户表时,打印一条查询语句,通过用户对象去获取订单数量时(执行第二行),不会查询订单的详细数据,只会用count获取数量
lazy=extra fetch=join:查询用户表数据的时候就直接打印一条连接查询的sql语句(执行第一行,就会打印sql,且只打印这一条)
在这里插入图片描述
(查询多个用户及其订单)
lazy=true fetch=subselect:使用集合时,才会加载,并且使用子查询的方式加载(执行第三行时,会使用一条子查询语句查询)
lazy=false fetch=subselect:查询用户数据时,也会立即用子查询查询其相关的订单信息
lazy=extra fetch=subselect:查询用户数据,打印一条sql语句查询用户表,查询订单数量的时候,会分别执行多条count语句查询每个用户的订单数;

上面的情况是针对,查询订单时只查询订单数量,对于需要查询订单具体信息时,如下图的代码所示:
在这里插入图片描述
(lazy=extra fetch=subselect这种组合情况打印的sql语句会有一些不同,对于需要获取订单数据的时候,会打印子查询获取)

三、在many-to-one标签中(多对一)

下面的列子,是以从订单找客户的角度。

  • lazy:
    false:加载订单时,会立刻加载客户数据
    proxy:根据客户的类加载策略来决定
  • fetch:
    select:默认值,普通select语句查询加载
    join:表链接语句查询集合数据

总结

以上就是Hibernate的加载策略设置的全部内容了。其实理解了每一个加载策略属性下不同值的意思,组合情况也就很好理解了。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值