抓取策略
案例一
<!--默认值为”select” -->
<set name="students" lazy="true" fetch="select">
/**
* 发出两条sql语句
*/
@Test
public void testSetFetch_Select(){
Session session = sessionFactory.getCurrentSession();
Transaction transaction = session.beginTransaction();
Classes classes = (Classes)session.get(Classes.class, 1L);
Set<Student> students = classes.getStudents();
for(Student student:students){
System.out.println(student.getName());
}
transaction.commit();
}
上述的图中会发出n+1条sql语句,1代表查询classes表的数据,n代表classes表中的记录数
Hibernate:
select
classes0_.cid as cid0_0_,
classes0_.name as name0_0_
from
Classes classes0_
where
classes0_.cid=?
Hibernate:
select
students0_.cid as cid0_1_,
students0_.sid as sid1_,
students0_.sid as sid1_0_,
students0_.name as name1_0_,
students0_.cid as cid1_0_
from
Student students0_
where
students0_.cid=?
案例二
<set name="students" lazy="true" fetch="join">
Hibernate:
select
classes0_.cid as cid0_1_,
classes0_.name as name0_1_,
students1_.cid as cid0_3_,
students1_.sid as sid3_,
students1_.sid as sid1_0_,
students1_.name as name1_0_,
students1_.cid as cid1_0_
from
Classes classes0_
left outer join
Student students1_
on classes0_.cid=students1_.cid
where
classes0_.cid=?
案例三
<set name="students" lazy="true" fetch="subselect">
/**
* 查询所有的班级的所有的学生
*/
@Test
public void testSubSelect(){
Session session = sessionFactory.getCurrentSession();
Transaction transaction = session.beginTransaction();
List<Classes> classesList = session.createQuery("from Classes").list();
for(Classes classes:classesList){
Set<Student> students = classes.getStudents();
for(Student student:students){
System.out.println(student.getName());
}
}
transaction.commit();
}
Hibernate:
select
classes0_.cid as cid0_,
classes0_.name as name0_
from
Classes classes0_
Hibernate:
select
students0_.cid as cid0_1_,
students0_.sid as sid1_,
students0_.sid as sid1_0_,
students0_.name as name1_0_,
students0_.cid as cid1_0_
from
Student students0_
where
students0_.cid in (
select
classes0_.cid
from
Classes classes0_
)
案例四
/**
* 查询cid为1,2,3的班级的信息和这些班级中学生的信息
*/
@Test
public void testSubSelect_2(){
Session session = sessionFactory.getCurrentSession();
Transaction transaction = session.beginTransaction();
List<Classes> classesList = session.createQuery("from Classes where cid in(1,2,3)").list();
for(Classes classes:classesList){
Set<Student> students = classes.getStudents();
for(Student student:students){
System.out.println(student.getName());
}
}
transaction.commit();
}
Hibernate:
select
classes0_.cid as cid0_,
classes0_.name as name0_
from
Classes classes0_
where
classes0_.cid in (
1 , 2 , 3
)
Hibernate:
select
students0_.cid as cid0_1_,
students0_.sid as sid1_,
students0_.sid as sid1_0_,
students0_.name as name1_0_,
students0_.cid as cid1_0_
from
Student students0_
where
students0_.cid in (
select
classes0_.cid
from
Classes classes0_
where
classes0_.cid in (
1 , 2 , 3
)
)
总结
需要一次性把数据全部查询出来,用join
如果经过需求分析翻译出来有子查询,用subselect
默认情况下用select
抓取策略的研究前提必须是关联对象,是研究怎么样发出sql语句来提取数据的
抓取策略只不过是hibernate给大家提供的一种优化策略而已。
因为抓取策略是写在映射文件中的,所以只能写一次。如果要想改变sql语句的结构,则用hql语句。
Subselect可以防止n+1条sql语句的出现
抓取策略和懒加载
1、研究对象为set集合
2、如果抓取策略为join,则懒加载失效
3、如果抓取策略为select,则保持懒加载的策略
4、如果抓取策略为subselect,则保持懒加载的策略
二级缓存
概念
1、为sessionFactory级别的缓存
2、二级缓存存放的是公共的数据
3、二级缓存的生命周期和sessionFactory的生命周期一样
4、二级缓存的存和取的策略
把数据存放到二级缓存中
Get方法
@Test
public void testGet(){
Session session = sessionFactory.openSession();
Classes classes = (Classes)session.get(Classes.class, 2L);
System.out.println(sessionFactory.getStatistics().getEntityLoadCount());
session.close();
session = sessionFactory.openSession();
classes = (Classes)session.get(Classes.class, 2L);
session.close();
}
Hibernate:
select
classes0_.cid as cid0_0_,
classes0_.name as name0_0_
from
Classes classes0_
where
classes0_.cid=?
只发出了一条sql语句,第二个session.get方法的对象来自于二级缓存
2、当session执行save或者update方法的时候,没有必要放入到二级缓存中,因为修改的因素很大。
二级缓存的统计机制
<!--
开启hibernate的统计机制
-->
<property name="hibernate.generate_statistics">true</property>
二级缓存的特点
一般情况下把一个对象放入到二级缓存中,对象的属性一般是不会改变的。
利用CacheModel控制二级缓存的对象
Hibernate:
select
classes0_.cid as cid0_0_,
classes0_.name as name0_0_
from
Classes classes0_
where
classes0_.cid=?
1
Hibernate:
update
Classes
set
name=?
where
cid=?
222
二级缓存的磁盘化
<diskStore path="e:\\TEMP1"/>
<Cache
name="cn.itcast.sh08.hibernate.domain.Classes"
maxElementsInMemory="3"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
maxElementsOnDisk="10000000"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU"
/>