Web开发 | Hibernate - 14.查询功能优化

一、延迟加载

延迟加载先获取到代理对象,当真正使用到该对象中的属性的时候,
才会发送 SQL 语句,是 Hibernate 框架提升性能的方式
Hibernate框架提供的延迟加载,有两种方式
类级别的延迟加载 关联级别的延迟加载
session.load();默认就是延迟加载的方法 Customer c = session.get(); 不是延迟加载
c.getLinkmans();才会发生SQL语句

1、JavaBean与映射配置文件

新建项目Hibernate5_d04_c03,引入必要的jar包、配置、util类

  /Hibernate5_d04_c03/src/hibernate/domain/Customer.java
程序代码如下:

package hibernate.domain;

import java.util.HashSet;
import java.util.Set;

public class Customer {
    private Long cust_id;
    private String cust_name;
    private Long cust_user_id;
    private Long cust_create_id;
    private String cust_source;
    private String cust_industry;
    private String cust_level;
    private String cust_linkman;
    private String cust_phone;
    private String cust_mobile;

    //set集合表示多个联系人
    private Set<LinkMan> linkMans = new HashSet<>();

    /**  
    * @Title: Customer
    * 需要提供一个空的构造方法,hibernate 默认使用空的构造方法来创建对象      
    */
    public Customer() {
        // TODO Auto-generated constructor stub
    }
    /**  
    * @Title: Customer  
    * @param cust_name
    * @param cust_level    
    */
    public Customer(String cust_name, String cust_level) {
        this.cust_name = cust_name;
        this.cust_level = cust_level;
    }

    //省略getter和setter方法
}

  /Hibernate5_d04_c03/src/hibernate/domain/LinkMan.java
程序代码如下:

package hibernate.domain;

public class LinkMan {
    private Integer lkm_id;
    private String lkm_name;
//  lkm_cust_id 外键,不用写
    private String lkm_gender;
    private String lkm_phone;
    private String lkm_mobile;
    private String lkm_email;
    private String lkm_qq;
    private String lkm_position;
    private String lkm_memo;

    //客户类
    private Customer customer;

    //省略getter和setter方法
}

  /Hibernate5_d04_c03/src/hibernate/domain/Customer.hbm.xml
程序代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <!-- javabean与表之间的对应关系 -->
    <class name="hibernate.domain.Customer" table="cst_customer">
        <!-- 主键对应 -->
        <id name="cust_id" column="cust_id">
            <!-- 主键策略(与自增长相关) -->
            <generator class="native"></generator>
        </id>
        <!-- 其他字段 -->
        <property name="cust_name" column="cust_name"></property>
        <property name="cust_user_id" column="cust_user_id"></property>
        <property name="cust_create_id" column="cust_create_id"></property>
        <property name="cust_source" column="cust_source"></property>
        <property name="cust_industry" column="cust_industry"></property>
        <property name="cust_level" column="cust_level"></property>
        <property name="cust_linkman" column="cust_linkman"></property>
        <property name="cust_phone" column="cust_phone"></property>
        <property name="cust_mobile" column="cust_mobile"></property>
        <!-- 一对多配置 -->
        <set name="linkMans" inverse="true"  >
            <!-- 外键 -->
            <key column="lkm_cust_id"></key>
            <!-- 一对多关系 -->
            <one-to-many class="hibernate.domain.LinkMan"/>
        </set>

    </class>
</hibernate-mapping>

  /Hibernate5_d04_c03/src/hibernate/domain/LinkMan.hbm.xml
程序代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="hibernate.domain.LinkMan" table="cst_linkman">
        <id name="lkm_id" column="lkm_id">
            <generator class="native"></generator>
        </id>
        <property name="lkm_name" column="lkm_name"></property>
        <property name="lkm_gender" column="lkm_gender"></property>
        <property name="lkm_phone" column="lkm_phone"></property>
        <property name="lkm_mobile" column="lkm_mobile"></property>
        <property name="lkm_email" column="lkm_email"></property>
        <property name="lkm_qq" column="lkm_qq"></property>
        <property name="lkm_position" column="lkm_position"></property>
        <property name="lkm_memo" column="lkm_memo"></property>
        <!-- 多方配置 -->
        <many-to-one name="customer" class="hibernate.domain.Customer"
        column="lkm_cust_id" ></many-to-one>
    </class>
</hibernate-mapping>

  /Hibernate5_d04_c03/src/hibernate.cfg.xml
程序代码如下:

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE hibernate-configuration PUBLIC
    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
    <session-factory>
        <!-- 必选配置 -->
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
                <!-- jdbc:mysql:///hibernate_day01 -->
        <property name="hibernate.connection.url">jdbc:mysql://127.0.0.1:3306/hibernate_day04</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.connection.password">root</property>
                <!--数据库方言 使用的数据库类型  -->
        <property name="hibernate.dialect org.hibernate.dialect.MySQLDialect"></property>

        <!-- 可选配置 -->
                <!-- 在控制台输出sql语句 -->
        <property name="show_sql">true</property>
                <!-- 在控制台输出的sql语句格式化 -->
        <property name="hibernate.format_sql">true</property>
                <!-- 配置c3p0连接池 -->
                    <!-- C3P0 的供应商 -->
        <property name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>
                    <!-- 最小连接 -->
        <property name="hibernate.c3p0.min_size">5</property>
                    <!-- 最大连接数 -->
        <property name="hibernate.c3p0.max_size">10</property>
                    <!-- 每 120 秒检查空闲连接 -->
        <property name="hibernate.c3p0.timeout">120</property>
                <!-- 自动建表 -->
        <property name="hibernate.hbm2ddl.auto">update</property>
                <!-- 把session绑定到当前线程中,使用getCurrentSession()获取当前session -->
        <property name="hibernate.current_session_context_class">thread</property>

        <!-- 映射文件 -->
        <mapping resource="hibernate/domain/Customer.hbm.xml"/>
        <mapping resource="hibernate/domain/LinkMan.hbm.xml"/>
    </session-factory>
</hibernate-configuration>

2、类级别的延迟加载
Session对象的load方法默认就是延迟加载。
Customer c = session.load(Customer.class, 1L);没有发送SQL语句,
当使用该对象的属性时,才发送SQL语句。

使类级别的延迟加载失效:
    在<class>标签上配置 lazy=”false”
    Hibernate.initialize(Object proxy);

  /Hibernate5_d04_c03/src/hibernate/test/TestLazy.java
程序代码如下:

package hibernate.test;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;

import hibernate.domain.Customer;
import hibernate.util.HibernateUtils;
import sun.print.resources.serviceui;

public class TestLazy {
    /*
    * 延迟加载概念:没有真正发生 sql 语句,查看该对象中属性值的时候,才会发生sql
    */

    //类级别的延迟加载
    @Test
    public void testLoad(){
        Session session = HibernateUtils.getCurrentSession();
        Transaction tr = session.beginTransaction();
        //获取id为1的客户
        //使用load方法获取数据,load方法具有延迟加载功能
        //设置断点
        Customer c = session.load(Customer.class, 1L);
        System.out.println(c.getCust_id());//有没有发送sql,没有发送
        //id是拿到了,但是并没有发送sql,
        //因为我们取id的时候,我们session只需要与数据表一关联,就变成了持久态
        //处于持久态时,id是存在内存中,所以没有发送sql
        System.out.println("===========");
        //打印客户名称
        System.out.println(c.getCust_name());//有没有发送sql,发送
        //name是通过发送sql后取得的,在缓存中

        tr.commit();
    }
}

断点调试测试
断点调试测试

测试结果:
执行 System.out.println(c.getCust_id());
打印了id值,但是没有发sql语句,
执行 System.out.println(c.getCust_name());
打印了sql语句,
说明hibernate框架在我们需要数据时才去数据库查询,
这样可以提升程序性能,这是延迟加载的作用。

3、关联级别的延迟加载
默认是延迟加载

  /Hibernate5_d04_c03/src/hibernate/test/TestLazy.java
程序代码如下:

package hibernate.test;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;

import hibernate.domain.Customer;
import hibernate.util.HibernateUtils;
import sun.print.resources.serviceui;

public class TestLazy {
    ...
    //关联级别的延迟加载
    @Test
    public void testGet(){
        //获取1号客户,默认使用延迟加载
        Session session = HibernateUtils.getCurrentSession();
        Transaction tr = session.beginTransaction();
        Customer c = session.get(Customer.class, 1L);
        System.out.println(c.getCust_id());
        System.out.println("=============");
        //获取客户对应联系人的数量
        System.out.println(c.getLinkMans().size());

        tr.commit();
    }
}

断点调试测试
断点调试测试
断点调试测试

测试结果:
执行 Customer c = session.get(Customer.class, 1L);
发送查询客户表的sql,
执行 System.out.println(c.getLinkmans().size());
发送查询联系人的 sql,
说明hibernate的get方法在查询关联表时,使用的是延迟加载。

4、不使用延迟加载

  /Hibernate5_d04_c03/src/hibernate/domain/Customer.hbm.xml
程序代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <!-- javabean与表之间的对应关系 -->
    <!-- lazy="false" 不使用延迟加载  -->
    <class name="hibernate.domain.Customer" table="cst_customer" lazy="false">
        <!-- 主键对应 -->
        <id name="cust_id" column="cust_id">
            <!-- 主键策略(与自增长相关) -->
            <generator class="native"></generator>
        </id>
        <!-- 其他字段 -->
        <property name="cust_name" column="cust_name"></property>
        <property name="cust_user_id" column="cust_user_id"></property>
        <property name="cust_create_id" column="cust_create_id"></property>
        <property name="cust_source" column="cust_source"></property>
        <property name="cust_industry" column="cust_industry"></property>
        <property name="cust_level" column="cust_level"></property>
        <property name="cust_linkman" column="cust_linkman"></property>
        <property name="cust_phone" column="cust_phone"></property>
        <property name="cust_mobile" column="cust_mobile"></property>
        <!-- 一对多配置 -->
        <set name="linkMans" inverse="true"  >
            <!-- 外键 -->
            <key column="lkm_cust_id"></key>
            <!-- 一对多关系 -->
            <one-to-many class="hibernate.domain.LinkMan"/>
        </set>  
    </class>
</hibernate-mapping>
修改 Customer.hbm.xml 文件,
在<class>标签上配置 lazy=”false”,不使用延迟加载,
执行 Customer c = session.load(Customer.class, 1L);
控制台直接输出 sql 语句,说明没有使用延迟加载

二、在set标签上配置策略

< < <script type="math/tex" id="MathJax-Element-315"><</script>set > > 标签上的默认值是 fetch=”select”和 lazy=”true”
fetch 的取值 – 控制 SQL 语句生成的格式 select 默认值.发送查询语句
join 连接查询.发送的是一条迫切左外连接,配置了 join,lazy 就失效了
subselect 子查询.发送一条子查询查询其关联对象.(需要使用 list()方法进行测试)
lazy 的取值 – 查找关联对象的时候是否采用延迟 true 默认.延迟
false 不延迟
extra 及其懒惰
Hibernate 框架都采用了默认值,开发中基本上使用的都是默认值。

  /Hibernate5_d04_c03/src/hibernate/test/TestSetLazy.java
程序代码如下:

package hibernate.test;

import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;

import hibernate.domain.Customer;
import hibernate.util.HibernateUtils;
public class TestSetLazy {

    //加载策略测试
    @Test
    public void testSet1(){
        Session session = HibernateUtils.getCurrentSession();
        Transaction tr = session.beginTransaction();
        //获取一号客户
        Customer c = session.get(Customer.class, 1L);
        System.out.println(c.getCust_id());
        System.out.println("===============");
        System.out.println(c.getLinkMans().size());

        tr.commit();
    }
}

1、默认的的sql查询,对联系人表使用延迟加载,默认的配置

  /Hibernate5_d04_c03/src/hibernate/domain/Customer.hbm.xml
程序代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <!-- javabean与表之间的对应关系 -->
    <!-- lazy="false" 不使用延迟加载  -->
    <class name="hibernate.domain.Customer" table="cst_customer" >
        ...
        <!-- 一对多配置 -->
        <!-- 
            配置延迟加载策略
            fetch:发送sql语句的格式
            lazy:是否使用延迟加载
            fetch="select" lazy="true"  默认的的sql查询,对联系人表使用延迟加载,默认的配置
         -->
        <set name="linkMans" inverse="true"  fetch="select" lazy="true">
            <!-- 外键 -->
            <key column="lkm_cust_id"></key>
            <!-- 一对多关系 -->
            <one-to-many class="hibernate.domain.LinkMan"/>
        </set>
    </class>
</hibernate-mapping>
断点调试测试
执行Customer c = session.get(Customer.class, 1L);
发送一条SQL语句
执行System.out.println(c.getLinkMans().size());
发送一条SQL语句

总结:
默认延迟加载配置的情况

2、默认的的sql查询,对联系人表不使用延迟加载

  /Hibernate5_d04_c03/src/hibernate/domain/Customer.hbm.xml
程序代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <!-- javabean与表之间的对应关系 -->
    <!-- lazy="false" 不使用延迟加载  -->
    <class name="hibernate.domain.Customer" table="cst_customer" >
        ...
        <!-- 一对多配置 -->
        <!-- 
            配置延迟加载策略
            fetch:发送sql语句的格式
            lazy:是否使用延迟加载
            fetch="select" lazy="true"  默认的的sql查询,对联系人表使用延迟加载,默认的配置
            fetch="select" lazy="false" 默认的的sql查询,对联系人表不使用延迟加载
         -->

        <set name="linkMans" inverse="true"  fetch="select" lazy="false" >
            <!-- 外键 -->
            <key column="lkm_cust_id"></key>
            <!-- 一对多关系 -->
            <one-to-many class="hibernate.domain.LinkMan"/>
        </set>
    </class>
</hibernate-mapping>
断点调试测试
执行Customer c = session.get(Customer.class, 1L);
发送两条SQL语句

总结
不使用延迟加载的情况

3、默认的的sql查询,优化查询语句

  /Hibernate5_d04_c03/src/hibernate/domain/Customer.hbm.xml
程序代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <!-- javabean与表之间的对应关系 -->
    <!-- lazy="false" 不使用延迟加载  -->
    <class name="hibernate.domain.Customer" table="cst_customer" >
        ...
        <!-- 一对多配置 -->
        <!-- 
            配置延迟加载策略
            fetch:发送sql语句的格式
            lazy:是否使用延迟加载
            fetch="select" lazy="true"  默认的的sql查询,对联系人表使用延迟加载,默认的配置
            fetch="select" lazy="false" 默认的的sql查询,对联系人表不使用延迟加载
            fetch="select" lazy="extra" 默认的的sql查询,优化查询语句
         -->
        <set name="linkMans" inverse="true"  fetch="select" lazy="extra">
            <!-- 外键 -->
            <key column="lkm_cust_id"></key>
            <!-- 一对多关系 -->
            <one-to-many class="hibernate.domain.LinkMan"/>
        </set>
    </class>
</hibernate-mapping>
断点调试测试
执行Customer c = session.get(Customer.class, 1L);
发送一条SQL语句
执行System.out.println(c.getLinkMans().size());
发送一条SQL语句

总结:
但是较之前而言,第二条SQL语句发生了如下变化:
Hibernate: 
    select
        count(lkm_id) 
    from
        cst_linkman 
    where
        lkm_cust_id =?
优化了sql查询。     

4、使用迫切左外连接查询,lazy属性失效

  /Hibernate5_d04_c03/src/hibernate/domain/Customer.hbm.xml
程序代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <!-- javabean与表之间的对应关系 -->
    <!-- lazy="false" 不使用延迟加载  -->
    <class name="hibernate.domain.Customer" table="cst_customer" >
        ...
        <!-- 一对多配置 -->
        <!-- 
            配置延迟加载策略
            fetch:发送sql语句的格式
            lazy:是否使用延迟加载
            fetch="select" lazy="true"  默认的的sql查询,对联系人表使用延迟加载,默认的配置
            fetch="select" lazy="false" 默认的的sql查询,对联系人表不使用延迟加载
            fetch="select" lazy="extra" 默认的的sql查询,优化查询语句
            fetch="join" lazy="true"    使用迫切左外连接查询,lazy属性失效
         -->
        <set name="linkMans" inverse="true"  fetch="join" lazy="true" >
            <!-- 外键 -->
            <key column="lkm_cust_id"></key>
            <!-- 一对多关系 -->
            <one-to-many class="hibernate.domain.LinkMan"/>
        </set>
    </class>
</hibernate-mapping>
断点调试测试
执行Customer c = session.get(Customer.class, 1L);
发送一条SQL语句
执行System.out.println(c.getLinkMans().size());
没有发送SQL语句

总结:
只打印了1条sql语句,原先是2条,优化了sql查询。
fetch:SQL语句的格式发生变化,默认采用左连接查询
lazy属性设置为false或true都一样,因为只发送一条sql语句。

5、使用子查询,优化sql语句

(sql语句数量减少)ps:需要使用list方法测试

  /Hibernate5_d04_c03/src/hibernate/domain/Customer.hbm.xml
程序代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <!-- javabean与表之间的对应关系 -->
    <!-- lazy="false" 不使用延迟加载  -->
    <class name="hibernate.domain.Customer" table="cst_customer" >
        ...
        <!-- 
            配置延迟加载策略
            fetch:发送sql语句的格式
            lazy:是否使用延迟加载
            fetch="select" lazy="true"  默认的的sql查询,对联系人表使用延迟加载,默认的配置
            fetch="select" lazy="false" 默认的的sql查询,对联系人表不使用延迟加载
            fetch="select" lazy="extra" 默认的的sql查询,优化查询语句
            fetch="join" lazy="true"    使用迫切左外连接查询,lazy属性失效
            fetch="subselect" lazy="true" 使用子查询,优化sql语句(sql语句数量减少)ps:需要使用list方法测试
         -->
        <set name="linkMans" inverse="true"  fetch="subselect" lazy="true">
            <!-- 外键 -->
            <key column="lkm_cust_id"></key>
            <!-- 一对多关系 -->
            <one-to-many class="hibernate.domain.LinkMan"/>
        </set>
    </class>
</hibernate-mapping>

使用list方法测试

  /Hibernate5_d04_c03/src/hibernate/test/TestSetLazy.java
程序代码如下:

...
public class TestSetLazy {
    ...
    //加载策略测试
    @Test
    public void testSet2(){
        //查询所有客户,以及客户对应的联系人
        Session session = HibernateUtils.getCurrentSession();
        Transaction tr = session.beginTransaction();
        Query query = session.createQuery("from Customer");
        List<Customer> customers = query.list();
        for (Customer customer : customers) {
            System.out.println(customer.getLinkMans().size());
        }
        tr.commit();
    }
}
断点调试测试
执行List<Customer> customers = query.list();
发送一条SQL语句
第一次遍历for (Customer customer : customers) {
            System.out.println(customer.getLinkMans().size());
        }
发送一条SQL语句
第二次遍历开始,不发送SQL语句,依次把符合条件的遍历出来

总结:
fetch:SQL 语句的格式发生变化
只发送2条sql语句,优化了sql查询。

三、many-to-one标签上配置策略

<many-to-one > > <script type="math/tex" id="MathJax-Element-322">></script>标签上的默认值是 fetch=”select”和 lazy=”proxy”
fetch 的取值 – 控制 SQL 语句生成的格式 select 默认值.发送基本 select 语句查询
join 无效
lazy 的取值 – 控制加载关联对象是否采用延迟 false 不采用延迟加载
proxy 默认值.代理.
现在是否采用延迟由另一端的set上的lazy确定.
如果这端的 set 上的 lazy=”true”.proxy 的值就是 true(延迟加载);
如果 set 上 lazy=”false”.proxy 的值就是false(不采用延迟)

  /Hibernate5_d04_c03/src/hibernate/test/TestMany2One.java
程序代码如下:

package hibernate.test;

import java.util.List;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;

import hibernate.domain.Customer;
import hibernate.domain.LinkMan;
import hibernate.util.HibernateUtils;

public class TestMany2One {
    //多方配置加载策略
    @Test
    public  void testMany2One(){
        Session session = HibernateUtils.getCurrentSession();
        Transaction tr =session.beginTransaction();
        //获取1号客户
        //当Customer.hbm.xml的<set>标签中lazy="true"时,使用延迟加载
        //当Customer.hbm.xml的<set>标签中lazy="false"时,不使用延迟加载
        Customer c = session.get(Customer.class, 1L);
        System.out.println(c.getCust_id());
        System.out.println("================");
        //打印客户关联的联系人数量
        System.out.println(c.getLinkMans().size());
        tr.commit();
    }
}

  /Hibernate5_d04_c03/src/hibernate/domain/Customer.hbm.xml
程序代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <!-- javabean与表之间的对应关系 -->
    <!-- lazy="false" 不使用延迟加载  -->
    <class name="hibernate.domain.Customer" table="cst_customer" >
        <!-- 主键对应 -->
        <id name="cust_id" column="cust_id">
            <!-- 主键策略(与自增长相关) -->
            <generator class="native"></generator>
        </id>
        <!-- 其他字段 -->
        <property name="cust_name" column="cust_name"></property>
        <property name="cust_user_id" column="cust_user_id"></property>
        <property name="cust_create_id" column="cust_create_id"></property>
        <property name="cust_source" column="cust_source"></property>
        <property name="cust_industry" column="cust_industry"></property>
        <property name="cust_level" column="cust_level"></property>
        <property name="cust_linkman" column="cust_linkman"></property>
        <property name="cust_phone" column="cust_phone"></property>
        <property name="cust_mobile" column="cust_mobile"></property>
        <!-- 一对多配置 -->
        <!-- 
            配置延迟加载策略
            fetch:发送sql语句的格式
            lazy:是否使用延迟加载
            fetch="select" lazy="true"  默认的的sql查询,对联系人表使用延迟加载,默认的配置
         -->
        <set name="linkMans" inverse="true" lazy="true"  >
            <!-- 外键 -->
            <key column="lkm_cust_id"></key>
            <!-- 一对多关系 -->
            <one-to-many class="hibernate.domain.LinkMan"/>
        </set>
    </class>
</hibernate-mapping>

  /Hibernate5_d04_c03/src/hibernate/domain/LinkMan.hbm.xml
程序代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="hibernate.domain.LinkMan" table="cst_linkman">
        <id name="lkm_id" column="lkm_id">
            <generator class="native"></generator>
        </id>
        <property name="lkm_name" column="lkm_name"></property>
        <property name="lkm_gender" column="lkm_gender"></property>
        <property name="lkm_phone" column="lkm_phone"></property>
        <property name="lkm_mobile" column="lkm_mobile"></property>
        <property name="lkm_email" column="lkm_email"></property>
        <property name="lkm_qq" column="lkm_qq"></property>
        <property name="lkm_position" column="lkm_position"></property>
        <property name="lkm_memo" column="lkm_memo"></property>
        <!-- 多方配置 -->
        <!-- fetch="select":基本 SQL 语句,默认多条SQL语句
             lazy="proxy":看一方的配置
        -->
        <many-to-one fetch="select" lazy="proxy" name="customer" class="hibernate.domain.Customer"
        column="lkm_cust_id" ></many-to-one>
    </class>
</hibernate-mapping>
1、当Customer.hbm.xml中lazy=”true”时
断点调试测试
执行System.out.println(c.getCust_id());
发送一条SQL语句
执行System.out.println(c.getLinkMans().size());
发送一条SQL语句

总结:
Customer.hbm.xml的<set>标签中lazy="true",
LinkMan.hbm.xml的<many-to-one>标签中fetch="select" lazy="proxy",
使用延迟加载
2、当Customer.hbm.xml中lazy=”false”时
断点调试测试
执行System.out.println(c.getCust_id());
发送两条SQL语句

总结:
Customer.hbm.xml的<set>标签中lazy="false",
LinkMan.hbm.xml的<many-to-one>标签中fetch="select" lazy="proxy",
不使用延迟加载

四、批量抓取

  /Hibernate5_d04_c03/src/hibernate/test/TestMany2One.java
程序代码如下:

package hibernate.test;

import java.util.List;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;

import hibernate.domain.Customer;
import hibernate.domain.LinkMan;
import hibernate.util.HibernateUtils;

public class TestMany2One {
    ...
    //多方配置加载策略
    //批量抓取,能简化生成的SQL语句
    //获取客户下的联系人的信息
    @Test
    public void testGetAll(){
        Session session = HibernateUtils.getCurrentSession();
        Transaction tr = session.beginTransaction();
        //查询所有客户
        //获取客户下的联系人的信息
        //设置断点
        List<Customer> customers = session.createQuery("from Customer").list();
        for (Customer customer : customers) {
            for (LinkMan linkMan : customer.getLinkMans()) {
                System.out.println(linkMan);
            }
        }
        tr.commit();
    }
}

在 Linkman 类中添加 toString()方法,方便打印

  /Hibernate5_d04_c03/src/hibernate/domain/LinkMan.java
程序代码如下:

package hibernate.domain;

public class LinkMan {
    ...
    @Override
    public String toString() {
        return "LinkMan [lkm_id=" + lkm_id + ", lkm_name=" + lkm_name + ", lkm_gender=" + lkm_gender + ", lkm_phone="
                + lkm_phone + ", lkm_mobile=" + lkm_mobile + ", lkm_email=" + lkm_email + ", lkm_qq=" + lkm_qq
                + ", lkm_position=" + lkm_position + ", lkm_memo=" + lkm_memo + ", customer=" + customer + "]";
    }

}

  /Hibernate5_d04_c03/src/hibernate/domain/Customer.hbm.xml
程序代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <!-- javabean与表之间的对应关系 -->
    <!-- lazy="false" 不使用延迟加载  -->
    <class name="hibernate.domain.Customer" table="cst_customer" >
        ...
        <!-- 一对多配置 -->
        <!-- 
                        batch-size="10" 批量获取数据,10:每次获取10条数据
         -->
        <set name="linkMans" inverse="true"  batch-size="10">
            <!-- 外键 -->
            <key column="lkm_cust_id"></key>
            <!-- 一对多关系 -->
            <one-to-many class="hibernate.domain.LinkMan"/>
        </set>

    </class>
</hibernate-mapping>

设置批量抓取之前
调试测试
发送很多条SQL语句,逐条遍历输出
设置批量抓取后
调试测试
发送少量SQL语句
以10条为界线分批遍历输出
最后一次遍历可能不满10条

五、延迟加载总结

延迟加载总结

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值