作者:何征天
课程视频地址:https://ke.qq.com/course/273907
1.1. 需求分析
1. 对Hibernate框架的查询进行优化
1. 延迟加载先获取到代理对象,当真正使用到该对象中的属性的时候,才会发送SQL语句,是Hibernate框架提升性能的方式
2.类级别的延迟加载
* Session对象的load方法默认就是延迟加载
* Customer c = session.load(Customer.class, 1L);没有发送SQL语句,当使用该对象的属性时,才发送SQL语句
* 使类级别的延迟加载失效
* 在
* Hibernate.initialize(Objectproxy);
【准备工作】
【示例】
1.在com.igeek.demo4下新建Demo1类,代码如下:
packagecom.igeek.demo4;
import org.hibernate.Session; import org.hibernate.Transaction; import org.junit.Test;
import cn.igeekutil.HibernateUtils;
publicclass Demo1 { /** * 延迟加载概念:没有真正发生sql语句,查看该对象中属性值的时候,才会发生sql */ @Test publicvoid run1(){ Session session = HibernateUtils.getCurrentSession(); Transaction tr = session.beginTransaction(); //1号客户,默认使用延迟加载 //设置断点 Customer c = session.load(Customer.class, 1L); System.out.println(c.getCust_id()); System.out.println("=================="); //打印客户名称 System.out.println(c.getCust_name()); tr.commit(); } } |
2.通过断点调试测试,在执行System.out.println(c.getCust_id());后,打印了id值,但是没有发sql语句,在执行System.out.println(c.getCust_name());后才打印sql语句,说明hibernate框架在我们需要数据时才去数据库查询,这样可以提升程序性能,这是延迟加载的作用。
3.修改Customer.hbm.xml文件,在
<class name="com.igeek.demo4.Customer" table="cst_customer" lazy="false"> |
3. 关联级别的延迟加载(查询某个客户,当查看该客户下的所有联系人是是否是延迟加载)
* 默认是延迟加载
【示例】
1.在Demo1类中添加测试代码:
//关联级别的延迟加载 @Test publicvoid run2(){ Session session = HibernateUtils.getCurrentSession(); Transaction tr = session.beginTransaction(); //1号客户,默认使用延迟加载 //设置断点 Customer c = session.get(Customer.class, 1L); System.out.println(c.getCust_id()); System.out.println("===================="); //打印客户关联的联系人数量 System.out.println(c.getLinkmans().size()); tr.commit(); } |
2.修改Customer.hbm.xml文件中lazy属性,然后通过断点测试
<class name="com.igeek.demo4.Customer" table="cst_customer" > |
测试结果:执行Customer c = session.get(Customer.class, 1L);发送查询客户表的sql,执行System.out.println(c.getLinkmans().size());发送查询联系人的sql,说明hibernate的get方法在查询关联表时,使用的是延迟加载。
1.查询策略:使用Hibernate查询一个对象的时候,查询其关联对象.应该如何查询.是Hibernate的一种优化手段!!!
2. Hibernate 框架的检索策略解决的问题Customer c1 =(Customer) session.get(Customer.class, 1);
System.out.println(c1.getLinkmans().size());
* lazy属性解决查询的时机的问题,需要配置是否采用延迟加载!!
* 查询的语句形式
List
for(Customerc : list){
System.out.println(c.getLinkmans());
}
* fetch属性就可以解决查询语句的形式的问题!!
1. 在
* fetch的取值 -- 控制SQL语句生成的格式
* select --默认值.发送查询语句
* join --连接查询.发送的是一条迫切左外连接!!!配置了join.lazy就失效了
* subselect --子查询.发送一条子查询查询其关联对象.(需要使用list()方法进行测试)
* lazy的取值 -- 查找关联对象的时候是否采用延迟!
* true -- 默认.延迟
* false -- 不延迟
* extra --及其懒惰
2. set标签上的默认值是fetch="select"和lazy="true"
3. 总结:Hibernate框架都采用了默认值,开发中基本上使用的都是默认值。
【示例】
1.在Demo1类中添加测试代码:
//加载策略测试 @Test publicvoid run3(){ Session session = HibernateUtils.getCurrentSession(); Transaction tr = session.beginTransaction(); //1号客户,默认使用延迟加载 //设置断点 Customer c = session.get(Customer.class, 1L); System.out.println(c.getCust_id()); System.out.println("===================="); //打印客户关联的联系人数量 System.out.println(c.getLinkmans().size()); tr.commit(); } |
2.修改Customer.hbm.xml配置文件,使用断点测试,观察结果。
<set name="linkmans" fetch="select" lazy="true"> |
3.修改Customer.hbm.xml配置文件,把lazy属性设置为false,再次测试。
<set name="linkmans" fetch="select" lazy="false"> |
4.修改Customer.hbm.xml配置文件,把lazy属性设置为extra,再次测试。
<set name="linkmans" fetch="select" lazy="extra"> |
5.修改Customer.hbm.xml配置文件,把fetch属性设置为join,再次测试,发现只打印了1条sql语句,原先是2条,优化了sql查询。lazy属性设置为false或true都一样,因为只发送一条sql语句。
<set name="linkmans" fetch="join" lazy="true"> |
6.在Demo1类中添加测试方法,测试发现每查询一次客户就发送一条sql,显然不合理
//加载策略测试 @Test publicvoid run4(){ Session session = HibernateUtils.getCurrentSession(); Transaction tr = session.beginTransaction(); //查询所有客户 //设置断点 List for (Customer customer : customers) { System.out.println(customer.getLinkmans().size()); } tr.commit(); } |
7.修改Customer.hbm.xml配置文件,把fetch属性设置为subselect,再次测试,只发送2条sql语句,hibernate优化了查询。
<set name="linkmans" fetch="subselect" lazy="true"> |
1. 在
* fetch的取值 -- 控制SQL的格式
* select --默认。发送基本select语句查询
* join --无效
* lazy的取值 -- 控制加载关联对象是否采用延迟
* false --不采用延迟加载
* proxy --默认值.代理.现在是否采用延迟
* 由另一端的
* 如果set上lazy=”false”.proxy的值就是false(不采用延迟)
2. 在
【示例】
1.在Demo1类中添加测试代码:
//多方配置加载策略 @Test publicvoid run5(){ Session session = HibernateUtils.getCurrentSession(); Transaction tr = session.beginTransaction(); //1号客户,默认使用延迟加载 Customer c = session.get(Customer.class, 1L); System.out.println(c.getCust_id()); System.out.println("===================="); //打印客户关联的联系人数量 System.out.println(c.getLinkmans().size()); tr.commit(); } |
2.修改Customer.hbm.xml
<set name="linkmans" lazy="true"> |
3.修改Linkman.hbm.xml
<many-to-one fetch="select" lazy="proxy" name="Customer" class="com.igeek.demo4.Customer" column="lkm_cust_id">many-to-one> |
4.把Customer.hbm.xml中的lazy改成 true 和false 分别测试,查看结果。
在Demo2中添加测试方法
//批量抓取,能简化生成的SQL语句 @Test publicvoid run6(){ Session session = HibernateUtils.getCurrentSession(); Transaction tr = session.beginTransaction(); //查询所有客户 //设置断点 List for (Customer customer : customers) { for (Linkman linkman : customer.getLinkmans()) { System.out.println(linkman); } } tr.commit(); } |
@Override public String toString() { return"Linkman [lkm_id=" + lkm_id + ", lkm_name=" + lkm_name + ", lkm_cust_id=" + lkm_cust_id + ", 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 + "]"; } |
* 会发生多条SQL语句
2. 可以在
<set name="linkmans" batch-size="10"> |