一、延迟加载
延迟加载先获取到代理对象,当真正使用到该对象中的属性的时候,
才会发送 SQL 语句,是 Hibernate 框架提升性能的方式
Hibernate框架提供的延迟加载,有两种方式 | |
类级别的延迟加载 | 关联级别的延迟加载 |
session.load();默认就是延迟加载的方法 | Customer c = session.get(); 不是延迟加载 c.getLinkmans();才会发生SQL语句 |
1、JavaBean与映射配置文件
/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();
}
}
![断点调试测试](https://i-blog.csdnimg.cn/blog_migrate/c6a71a92e007762bd9772b84e2397ad4.jpeg)
![断点调试测试](https://i-blog.csdnimg.cn/blog_migrate/ec997e62e0e7b9bc7dea56b2e72073aa.jpeg)
测试结果:
执行 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();
}
}
![断点调试测试](https://i-blog.csdnimg.cn/blog_migrate/5ea59b48bafca87c19ab1ea1361fab72.jpeg)
![断点调试测试](https://i-blog.csdnimg.cn/blog_migrate/2072f89b06c8ac98f8bebfd09e5f888c.jpeg)
![断点调试测试](https://i-blog.csdnimg.cn/blog_migrate/01f3ccfe9fc34cd563dc13079c994826.jpeg)
测试结果:
执行 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语句
/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>
/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();
}
}
/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条
五、延迟加载总结
![延迟加载总结](https://i-blog.csdnimg.cn/blog_migrate/0e12b33cdfdd4fc2f30c4a43bced58d7.png)