Hibernate入门第十四讲——Hibernate的优化方案与抓取策略
发布日期:2021-06-30 18:00:35 浏览次数:2 分类:技术文章

本文共 14748 字,大约阅读时间需要 49 分钟。

Hibernate的优化方案

一般而言,我们可以从以下两方面来优化Hibernate。

  • HQL语句的优化;
  • 一级缓存的优化。

下面我就稍微从这两方面说道说道,如有不足之处,还请指出。

HQL语句的优化

HQL语句可以从以下几个方面进行优化:

  • 使用参数绑定
    • 使用参数绑定的原因是让数据库一次解析SQL,对后续的重复请求可以使用生成好的执行计划,这样做节省CPU时间和内存;
    • 避免SQL注入。
  • 尽量少使用NOT:如果where子句中包含not关键字,那么执行时该字段的索引失效;
  • 尽量使用where来替换having:having在检索出所有记录后才对结果集进行过滤,这个处理需要一定的开销,而where子句限制记录的数目,能减少这方面的开销;
  • 减少对表的查询:在含有子查询的HQL中,尽量减少对表的查询,降低开销;
  • 使用表的别名:当在HQL语句中连接多个表时,使用别名,提高程序阅读性,并把别名前缀与每个列连接上,这样一来,可以减少解析时间并减少列歧义引起的语法错误;
  • 实体的更新与删除:在Hibernate3以后支持HQL的update与delete操作。

一级缓存的优化

一级缓存也叫做Session缓存,在一个Hibernate Session中有效,这级缓存的可干预性不强,大多于Hibernate自动管理,但它提供清除缓存的方法,这对大批量增加(更新)操作而言是有效果的,例如,同时增加十万条记录,按常规进行,很可能会出现异常,这时可能需要手动清除一级缓存,session.evict以及session.clear。

Hibernate的抓取策略(对于查询关联对象的一种优化)

延迟加载

延迟加载是Hibernate为提高程序执行的效率而提供的一种机制,即只有真正使用该对象的数据时才会创建。说人话就是:延迟加载也叫懒加载(lazy),当执行到该行代码的时候,不会发送语句去进行查询,只有在真正使用这个对象的其他属性的时候才会真正发送SQL语句进行查询。还记得load方法采用的策略是延迟加载,get方法采用的策略是立即加载吗?延迟加载可分为两类,它们分别是:

  • 类级别的延迟加载;
  • 关联级别的延迟加载。

下面我就简单说说它俩。

类级别的延迟加载

类级别的延迟加载指的是通过load方法查询某个对象的时候,是否采用延迟(默认采用的就是延迟加载)。例如,

Customer c = session.load(Customer.class, 1l);

类级别的延迟加载可以通过<class>元素的lazy属性来设置,默认值是true。即默认是延迟加载。如果为了显示的声明出来,那么我们可以在映射配置文件中设置如下,注意:<class>元素上的lazy属性只对普通属性有效,对关联对象无效。

在这里插入图片描述
如果想让类级别的延迟加载失效,那么该咋办呢?总共有三种方式可让类级别的延迟加载失效,下面我会分别介绍它们。

  • 第一种方式:将<class>元素上的lazy属性设置为false。
    为了便于演示这种方式,我们在com.meimeixia.hibernate.demo02包下编写一个LoadTest单元测试类,并在该类中编写如下demo01()测试方法。
    在这里插入图片描述
    以上程序证明了如果将<class>元素上的lazy属性设置为false,代表类级别的延迟加载失效,这时load与get方法就完全一样了,都是立即加载。
    虽然我们是知道了load方法采用的策略是延迟加载,get方法采用的策略是立即加载,但是什么时候用get方法,什么时候用load方法呢?如果你查询的数据非常大,例如说它里面有一些大的字段,这个时候建议你采用load方法,不要一上来就立即加载,把我们的内存占满,这样可以让我们的性能得到一部分的提升;如果你查询的数据非常少,直接get就无所谓了,因为它不会占用我们很多的内存
  • 第二种方式:将持久化类使用final修饰,例如:
    在这里插入图片描述
  • 第三种方式:调用Hibernate.initialize()方法,例如:
    在这里插入图片描述
    Hibernate这个框架是在dao层进行操作的,如果说我现在采用了一个load的方案去获取了一个对象,我们最终会把Session关闭再返回,那么我们就要把这个对象返回到service层,最后再返回到web层,这个时候load出来的代理对象其实还没有对数据进行初始化,也即它里面还没有真正有数据,返回的时候就出问题了,那如何对一个延迟的代理对象进行初始化呢?这个时候,你就要调用Hibernate.initialize()方法对load出来的代理对象初始化一把了。

关联级别的延迟加载

查询到某个对象,获得其关联的对象或属性,这种就称为关联级别的延迟加载。说得更大白话一点:关联级别的延迟加载指的是在查询到某个对象的时候,查询其关联的对象,是否采用延迟加载。例如,

Customer customer = session.get(Customer.class, 1l);customer.getLinkMans();//通过客户获得联系人的时候,联系人对象是否采用了延迟加载,这就称之为是关联级别的延迟加载

因为抓取策略往往会和关联级别的延迟加载一起使用,优化语句,所以下面就要研究抓取策略了。

抓取策略

抓取策略的概述

抓取策略指的是查找到某个对象后,通过这个对象去查询关联对象的信息时的一种策略。我们知道Hibernate中对象之间的关联关系有三种:

在这里插入图片描述
这里我们主要讲的是在<set><many-to-one>这两个标签上设置fetch、lazy属性,为何要设置这俩哥们呢?因为通过一个对象抓取到其关联对象时,需要发送SQL语句,SQL语句到底何时发送,发送成什么样的格式,这就需要通过抓取策略来进行配置了。

  • fetch属性主要描述的是SQL语句的格式,例如是多条,还是子查询,还是多表联查;
  • lazy属性用于控制SQL语句何时发送。

我在这里举个例子说明下,例如现在要查询一个客户,并且还要关联查询他名下的联系人。客户代表一的一方,在客户实体类中有Set集合来描述其名下的联系人,那么客户映射配置文件就应该是这样子的配置:

在这里插入图片描述
此时,我们就可以在set标签上设置fetch和lazy这两个属性了。
再比如,查询一个联系人时,要查询关联的客户信息。联系人代表多的一方,在联系人实体类中有Customer对象来描述其关联的客户,在联系人映射配置文件中我们使用的是<many-to-one>标签,如下图所示。
在这里插入图片描述
此时,我们亦可在该标签上设置fetch和lazy这两个属性。当然了,你也可在<one-to-one>标签上设置这两个属性。
知道抓取策略要干的事之后,接下来,我将会花大篇幅来讨论<set><many-to-one>这两个标签上的fetch属性和lazy属性到底该如何设置,以优化发送的SQL语句。

<set>标签上的fetch与lazy

<set>标签上的fetch和lazy这两属性主要是用于设置关联的集合信息的抓取策略。

  • fetch属性:抓取策略,用来控制在查询关联对象时的SQL语句的格式。其可取值有:
    • select:默认值,发送普通的select语句查询关联对象
    • join:发送一条迫切左外连接来查询关联对象;
    • subselect:发送一条子查询去查询其关联对象。
  • lazy:延迟加载,控制查询关联对象的时候是否延迟。其可取值有:
    • true:默认值,查询关联对象的时候,采用延迟加载
    • false:查询关联对象的时候,不采用延迟加载;
    • extra:极其懒惰,也就是说你用什么样的SQL语句,就发送什么样的SQL语句。

这样看来,fetch与lazy的组合就有九种了,其实不然,fetch与lazy的组合实际上只有七种,且听我娓娓道来。

第一种组合(默认情况)

在com.meimeixia.hibernate.demo02包下编写一个SetFetchTest单元测试类,并在该类中编写如下测试方法:

package com.meimeixia.hibernate.demo02;import org.hibernate.Session;import org.hibernate.Transaction;import org.junit.Test;import com.meimeixia.hibernate.domain.Customer;import com.meimeixia.hibernate.domain.LinkMan;import com.meimeixia.hibernate.utils.HibernateUtils;/** * 在
上的fetch和lazy * @author liayun * */public class SetFetchTest {
/* * 默认情况,即fetch="select"、lazy="true" */ @Test public void demo01() {
Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); //查询1号客户 Customer customer = session.get(Customer.class, 1l);//只会发送一条查询客户的sql语句(根据客户的ID),作断点调试 System.out.println(customer.getCust_name()); //查询1号客户的每个联系人的信息 for (LinkMan linkMan : customer.getLinkMans()) {
//又会根据客户的ID去查询联系人的sql语句 System.out.println(linkMan.getLkm_name()); } tx.commit(); } }

Customer customer = session.get(Customer.class, 1l);这句代码上加上一个断点,然后以debug的方式调试该程序,就能得出结论:会首先查询客户信息,当需要联系人信息时,才会关联查询联系人信息,并在Eclipse控制台打印如下SQL语句:

在这里插入图片描述

第二种组合(fetch设置为select、lazy设置为false)

首先,确保客户那方的映射配置文件是下面这样子的。

在这里插入图片描述
然后,在SetFetchTest单元测试类中编写如下测试方法:

/* * 设置fetch="select" lazy="false" */@Testpublic void demo03() {
Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); //查询1号客户 Customer customer = session.get(Customer.class, 1l);//直接就发送了两条sql语句,作断点调试 //一条是用来查询客户的名称(根据客户ID) //一条是用来查询客户所关联的联系人(根据客户ID) System.out.println(customer.getCust_name()); /* //查询1号客户的每个联系人的信息 for (LinkMan linkMan : customer.getLinkMans()) { System.out.println(linkMan.getLkm_name()); } */ System.out.println(customer.getLinkMans().size()); tx.commit();}

Customer customer = session.get(Customer.class, 1l);这句代码上加上一个断点,然后以debug的方式调试该程序,就能得出结论:当查询客户信息时,也会将联系人信息查询出来,也就是说联系人信息没有进行延迟查询,可以看到Eclipse控制台打印了如下的SQL语句:

在这里插入图片描述

第三种组合(fetch设置为select、lazy设置为extra)

首先,确保客户那方的映射配置文件是下面这样子的。

在这里插入图片描述
然后,在SetFetchTest单元测试类中编写如下测试方法:

/* * 设置fetch="select" lazy="extra" */@Testpublic void demo03() {
Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); //查询1号客户 Customer customer = session.get(Customer.class, 1l);//这儿只会发送了一条查询1号客户的sql语句,作断点调试 System.out.println(customer.getCust_name()); System.out.println(customer.getLinkMans().size());//你想要个数,那我就给你发送一条select count(*) from ... tx.commit();}

Customer customer = session.get(Customer.class, 1l);这句代码上加上一个断点,然后以debug的方式调试该程序,就能得出结论:当查询客户信息时,不会去查询联系人的信息,当需要该客户所关联的联系人个数时,也不会去查询联系人的信息,只会通过count来统计联系人的个数,可以这样讲,当我们使用Set集合的size()、contains()或isEmpty()等方法时,是不会去查询联系人的信息的。而且可以看到Eclipse控制台打印了SQL语句:

在这里插入图片描述

第四种组合(fetch设置为join、此时lazy失效)

如果fetch选择的是join方案,那么lazy它就会失效。生成的SQl语句采用的是迫切左外连(left outer join fetch),也就是说这个时候会多表联查,既然是多表联查,就会把信息都查询出来,它既然是一个迫切左外连接,那么它就会根据你的需求把信息封装到你指定的对象里面,所以lazy它就会失效。

为了测试这第四种组合,首先确保客户那方的映射配置文件是下面这样子的。
在这里插入图片描述
然后,在SetFetchTest单元测试类中编写如下测试方法:

/* * 设置fetch="join" lazy=失效 *  * fetch="join":发送一条迫切左外连接,直接就把两个表的数据全查询出来了, * 那么这个时候,其实你配置延迟还是不延迟,就已经没有效果了,也即lazy失效。 */@Testpublic void demo04() {
Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); //查询1号客户 Customer customer = session.get(Customer.class, 1l);//只发送一条迫切左外连接来查询记录,作断点调试 System.out.println(customer.getCust_name()); System.out.println(customer.getLinkMans().size());//这儿就不发生sql语句了 tx.commit();}

Customer customer = session.get(Customer.class, 1l);这句代码上加上一个断点,然后以debug的方式调试该程序,你将在Eclipse控制台看到如下SQL语句:

在这里插入图片描述

第五种组合(fetch设置为subselect、lazy设置为true)

为了测试这第五种组合,首先确保客户那方的映射配置文件是下面这样子的。

在这里插入图片描述
然后,在SetFetchTest单元测试类中编写如下测试方法:

/* * 设置fetch="subselect" lazy="true" *  */@SuppressWarnings("unchecked")@Testpublic void demo05() {
Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); List
list = session.createQuery("from Customer").list();//发送查询所有客户的sql语句 for (Customer customer : list) {
System.out.println(customer.getCust_name()); System.out.println(customer.getLinkMans().size());//发送的是一条子查询 } tx.commit();}

List<Customer> list = session.createQuery("from Customer").list();这句代码处打上一个断点,然后以debug的方式调试该程序,就能得出结论:会生成子查询,但是我们在查询客户所关联的联系人信息时采用的是延迟加载。你可以在Eclipse控制台看到如下SQL语句:

在这里插入图片描述

第六种组合(fetch设置为subselect、lazy设置为false)

为了测试这第六种组合,首先确保客户那方的映射配置文件是下面这样子的。

在这里插入图片描述
然后,在SetFetchTest单元测试类中编写如下测试方法:

/* * 设置fetch="subselect" lazy="false" *  */@SuppressWarnings("unchecked")@Testpublic void demo06() {
Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); List
list = session.createQuery("from Customer").list();//发送查询所有客户的sql语句 //并发送一条子查询 for (Customer customer : list) {
System.out.println(customer.getCust_name()); System.out.println(customer.getLinkMans().size()); } tx.commit();}

List<Customer> list = session.createQuery("from Customer").list();这句代码处打上一个断点,然后以debug的方式调试该程序,就能得出结论:会生成子查询,在查询客户信息时,就会将客户所关联的联系人信息也查询出来。你可以在Eclipse控制台看到如下SQL语句:

在这里插入图片描述

第七种组合(fetch设置为subselect、lazy设置为extra)

为了测试这第七种组合,首先确保客户那方的映射配置文件是下面这样子的。

在这里插入图片描述
然后,在SetFetchTest单元测试类中编写如下测试方法:

/* * 设置fetch="subselect" lazy="extra" *  */@SuppressWarnings("unchecked")@Testpublic void demo07() {
Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); List
list = session.createQuery("from Customer").list();//发送查询所有客户的sql语句 for (Customer customer : list) {
System.out.println(customer.getCust_name()); System.out.println(customer.getLinkMans().size());//这儿会发送查询客户所关联的联系人个数的sql语句 } tx.commit();}

List<Customer> list = session.createQuery("from Customer").list();这句代码处打上一个断点,然后以debug的方式调试该程序,就能得出结论:当查询客户信息时,不会去查询联系人的信息,当需要该客户所关联的联系人个数时,也不会去查询联系人的信息,只会通过count来统计联系人的个数,即会发出select count(lkm_id) from cst_linkman where lkm_cust_id =?这样的SQL语句查询出该客户所关联的联系人个数。你可以在Eclipse控制台看到如下SQL语句:

在这里插入图片描述

小结

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

<many-to-one>标签上的fetch与lazy

<set>标签上的fetch与lazy这两属性主要是设置在获取到代表一的一方时,如何去查询代表多的一方。在这一章节中,我们讨论的是在<many-to-one>(或者<one-to-one>)标签上如何设置fetch和lazy这两属性,然后去查询对方。对于我们的程序而言,就是在代表多的一方如何查询代表一的一方的信息。例如,获取到一个联系人对象,要查询其关联的客户信息。

  • fetch属性:抓取策略,用来控制在查询关联对象时的SQL语句的格式。其可取值有:

    • select:默认值,发送普通的select语句查询关联对象
    • join:发送一条迫切左外连接来查询关联对象。
  • lazy:延迟加载,控制查询关联对象的时候是否延迟。其可取值有:

    • proxy:默认值,是否采用延迟不由本方说了算,而是需要由另一方的类级别延迟策略来决定。也就是说proxy具体的取值取决于另一端的<class>上的lazy属性的值
    • false:查询关联对象,不采用延迟;
    • no-proxy:由于不会使用,故在此不讨论。

第一种组合(默认情况)

默认情况就是,在<many-to-one>标签上将fetch属性的值设置为select,lazy属性的值设置为proxy。

在这里插入图片描述
由于此时lazy属性的值为proxy,所以查询关联对象时,是否采用延迟不由本方说了算,而是需要由另一方的类级别延迟策略来决定。这样看来要分情况来讨论了。

  • 第一种情况:客户映射配置文件的<class>元素上的lazy属性设置为默认,说是默认,其实就是lazy属性值为true。

    在这里插入图片描述
    在com.meimeixia.hibernate.demo02包下编写一个OneFetchTest单元测试类,并在该类中编写如下测试方法:

    package com.meimeixia.hibernate.demo02;import org.hibernate.Session;import org.hibernate.Transaction;import org.junit.Test;import com.meimeixia.hibernate.domain.LinkMan;import com.meimeixia.hibernate.utils.HibernateUtils;/** * 
    上的fetch和lazy的测试 * @author liayun * */public class OneFetchTest {
    /* * 默认值,即设置fetch="select"、lazy="proxy" */ @Test public void demo01() {
    Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); LinkMan linkMan = session.get(LinkMan.class, 1l);//发送一条查询联系人的语句 System.out.println(linkMan.getLkm_name()); System.out.println(linkMan.getCustomer().getCust_name());//又会发送一条普通的select语句,去查询联系人所关联的客户 tx.commit(); } }

    LinkMan linkMan = session.get(LinkMan.class, 1l);这句代码处打上一个断点,然后以debug的方式调试该程序,就能得出结论:会首先发送一条SQL只查询联系人信息,客户信息会延迟,只有真正需要客户信息时,才会发送SQL来查询客户信息。你可以在Eclipse控制台看到打印的SQL语句:

    在这里插入图片描述

  • 第一种情况:客户映射配置文件的<class>元素上的lazy属性设置为false。

    在这里插入图片描述
    这时,同样以debug的方式运行demo01()方法,就能得出结论:当查询联系人时,同时也会将客户信息查询到,原因是Customer类的类级别延迟策略为false,也就是立即查询。你可以在Eclipse控制台看到打印的SQL语句:
    在这里插入图片描述

第二种组合(fetch设置为select、lazy设置为false)

这种情况就是,在<many-to-one>标签上将fetch属性的值设置为select,lazy属性的值设置为false。

在这里插入图片描述
然后,在OneFetchTest单元测试类中编写如下测试方法:

/* * fetch="select" lazy="false" */@Testpublic void demo02() {
Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); //发送一条查询联系人的语句,又会发送一条普通的select语句,去查询联系人所关联的客户 LinkMan linkMan = session.get(LinkMan.class, 1l); System.out.println(linkMan.getLkm_name()); System.out.println(linkMan.getCustomer().getCust_name()); tx.commit();}

LinkMan linkMan = session.get(LinkMan.class, 1l);这句代码处打上一个断点,然后以debug的方式调试该程序,就能得出结论:当查询联系人时,不会对客户信息进行延迟,会立即查询客户信息。你可以在Eclipse控制台看到打印的SQL语句:

在这里插入图片描述
温馨提示:这种组合不用理Customer类的类级别延迟策略。

第三种组合(fetch设置为join、此时lazy失效)

这种情况就是,在<many-to-one>标签上将fetch属性的值设置为join,此时lazy属性将失效,也就是说配啥都不好使。

在这里插入图片描述
然后,在OneFetchTest单元测试类中编写如下测试方法:

/* * fetch="join" lazy=失效 */@Testpublic void demo03() {
Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); //马上发送一条迫切左外连接,去查询联系人和联系人所关联的客户了 LinkMan linkMan = session.get(LinkMan.class, 1l); System.out.println(linkMan.getLkm_name()); System.out.println(linkMan.getCustomer().getCust_name()); tx.commit();}

LinkMan linkMan = session.get(LinkMan.class, 1l);这句代码处打上一个断点,然后以debug的方式调试该程序,就能得出结论:如果fetch的值为join,那么lazy将失效,这时会发送一条迫切左外连接来查询,也即立即查询。你可以在Eclipse控制台看到打印的SQL语句:

在这里插入图片描述
这种组合当然也就不需要搭理Customer类的类级别延迟策略了。

小结

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

批量抓取

我们在查询多个对象的关联对象时,可以采用批量抓取方式来对程序进行优化。要想实现批量抓取,可以在映射配置文件中通过batch-size属性来设置,其中batch-size属性的值表示一次抓取的条数。

获取客户的时候,同时批量去抓取联系人

首先检查两个PO类的映射配置文件是否如下:

  • Customer.hbm.xml
    在这里插入图片描述
  • LinkMan.hbm.xml
    在这里插入图片描述

为了查询出所有客户的联系人信息,我在com.meimeixia.hibernate.demo02包下编写了一个BatchFetchTest单元测试类,并在该类中编写了如下测试方法:

package com.meimeixia.hibernate.demo02;import java.util.List;import org.hibernate.Session;import org.hibernate.Transaction;import org.junit.Test;import com.meimeixia.hibernate.domain.Customer;import com.meimeixia.hibernate.domain.LinkMan;import com.meimeixia.hibernate.utils.HibernateUtils;/** * 批量抓取 * @author liayun * */public class BatchFetchTest {
/* * 获取客户的时候,同时批量去抓取联系人 * 需要在Customer.hbm.xml映射配置文件中的
标签上进行配置 * * batch-size默认值是1 */ @SuppressWarnings("unchecked") @Test public void demo01() {
Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); List
list = session.createQuery("from Customer").list(); for (Customer customer : list) {
System.out.println(customer.getCust_name()); for (LinkMan linkMan : customer.getLinkMans()) {
System.out.println(linkMan.getLkm_name()); } } tx.commit(); } }

运行以上方法,可发现Eclipse控制台打印了如下SQL语句:

在这里插入图片描述
从上面可以看到,首先发出了一条SQL来查询所有客户信息,然后根据客户的ID来查询联系人信息,因为有三个客户,所以发送了三条SQL,完成了查询联系人信息的操作。以上一共发送了四条SQL语句来完成操作,这就引出了一个N+1的经典问题。那咋解决这个问题呢?这时就需要采用批量抓取来解决N+1的问题了。
我们需要在客户类映射配置文件中的<set>标签上配置batch-size属性,如下:
在这里插入图片描述
这样再次运行demo01方法,你就可以看到Eclipse控制台打印了如下SQL语句:
在这里插入图片描述

获取联系人的时候,同时批量去抓取客户

为了查询出所有的联系人,然后根据联系人再查询出客户信息,我在BatchFetchTest单元测试类再编写如下测试方法:

/* * 获取联系人的时候,同时批量去抓取客户 * 也需要在Customer.hbm.xml映射配置文件中的
标签上进行配置 */@SuppressWarnings("unchecked")@Testpublic void demo02() {
Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); List
list = session.createQuery("from LinkMan").list(); for (LinkMan linkMan : list) {
System.out.println(linkMan.getLkm_name()); System.out.println(linkMan.getCustomer().getCust_name()); } tx.commit();}

运行以上方法,可发现Eclipse控制台打印了如下SQL语句:

在这里插入图片描述
从上面可以看到,首先发送了一条SQL查询出所有联系人,然后再根据联系人查询出所有客户,一共4条语句完成。这时也出现了同样的N+1问题,那么当然就需要采用批量抓取来解决这个N+1问题了。注意:联系人与客户,客户它是一个主表,联系人是一个从表。在设置批量抓取时都是在主表中设置。所以,我们就要在客户类映射配置文件中的<class>标签上配置batch-size属性了,如下:
在这里插入图片描述
这样再次运行demo02方法,你就可以看到Eclipse控制台打印了如下SQL语句:
在这里插入图片描述

小结

无论是根据哪一方来查询另一方,在进行批量抓取时,都是在父方设置。如果是要查询子方信息,那么我们是在父方那个映射配置文件的<set>标签上来设置batch-size属性,如果是从子方来查询父方,也是在父方那个映射配置文件的<class>标签上设置batch-size属性。如何区分父方与子方呢?有外键的表是子方(从表),关联方就是父方(主表)。

转载地址:https://liayun.blog.csdn.net/article/details/70768603 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:前端简单入门第六讲 认识JavaScript
下一篇:Hibernate入门第七讲——Hibernate中的事务管理

发表评论

最新留言

表示我来过!
[***.240.166.169]2024年04月24日 16时06分51秒