Hibernate学习笔记(八) — 懒加载与抓取策略

懒加载(Load On Demand)是一种独特而又强大的数据获取方法,它能够在用户滚动页面的时候自动获取更多的数据,而新得到的数据不会影响原有数据的显示,同时最大程度上减少服务器端的资源耗用。总结一句话:什么时候需要数据,什么时候加载。

一、懒加载

1.1 类的懒加载


由javassist产生的代理类与Classes类是继承关系,

session.load()方法产生的是代理对象,该代理类是持久化类的子类

/**
	 * 类的懒加载
	 */
	@Test
	public void testClass_lazy(){
		session = HibernateUtils.openSession();
		transaction = session.beginTransaction();
		Classes classes = (Classes) session.load(Classes.class, 1L);
		//classes.setName("asdj");
		System.out.println(classes.getName());//发出sql
		transaction.commit();
		session.close();
	}

1.2 集合的懒加载

/**
	 * 集合的懒加载
	 */
	@Test
	public void testCollect_lazy(){
		session = HibernateUtils.openSession();
		transaction = session.beginTransaction();
		
		Classes classes = (Classes) session.get(Classes.class, 1L);
		Set<Student> students = classes.getStudents();//不发出
		for (Student student : students) {//迭代的时候发出sql
			System.out.println(student.getName());
		}
		transaction.commit();
		session.close();
	}
	/**
	 * 更进一步的懒加载,设置extra,对于查询行数,最大值,最小值等
	 */
	@Test
	public void testlazy_extra(){
		session = HibernateUtils.openSession();
		transaction = session.beginTransaction();
		
		Classes classes = (Classes) session.get(Classes.class, 1L);
		Set<Student> students = classes.getStudents();
		System.out.println(students.size());
		transaction.commit();
		session.close();
	}

1.3 单端关联的懒加载(many2one的懒加载)


No-proxy 延迟加载 默认值

Proxy是加强版的延迟加载

因为是通过多的一方加载一的一方,所以对效率影响不大,所以一般情况下用默认值即可。


根据多的一端加载一的一端,事实上只是多查了一条数据,对性能几乎没有影响,比如根据学生来查班级

总结

懒加载是Hibernate提供的一种优化方式。

1、延迟加载在映射文件设置,而映射文件一旦确定,不能修改了。

2、延迟加载是通过控制sql语句的发出时间来提高效率的。

所以在开发中一般是不会去设置懒加载的配置。

二、抓取策略

抓取策略解决的是如何加载Set集合中数据的问题


public class FetchTest {

	private Session session;
	private Transaction transaction;
	private SessionFactory sessionFactory;

	/**
	 * fetch : select情况:
	 * 先查找Classes的id,在根据id查Student
	 * 	n+1条数据
	 * 		n:classes表中的条数
	 * 		1:classes表本身
	 */
	@Test
	public void testQueryAllStudent(){
		session = HibernateUtils.openSession();
		List<Classes> classes = session.createQuery("from Classes").list();
		for (Classes classes2 : classes) {
			System.out.println(classes2.getName());
			Set<Student> students = classes2.getStudents();
			for (Student student : students) {
				System.out.println(student.getName());
			}
		}
		session.close();
		
	}
	/**
	 * fetch : subselect情况:
	 * 因为该需求含有子查询,所以fetch 使用 subselect
	 * 2条sql
	 */
	@Test
	public void testQueryAllStudent2(){
		session = HibernateUtils.openSession();
		List<Classes> classes = session.createQuery("from Classes").list();
		for (Classes classes2 : classes) {
			System.out.println(classes2.getName());
			Set<Student> students = classes2.getStudents();
			for (Student student : students) {
				System.out.println(student.getName());
			}
		}
		session.close();
		
	}
	/**
	 * select
	 *    先查询一的一方的所有的对象(Classes),再根据每一个对象的id值查询其关联对象(Student)
	 */
	@Test
	public void testQueryClassesByCidAndStudents_Select(){
		Session session = HibernateUtils.openSession();
		Classes classes = (Classes)session.get(Classes.class, 1L);
		System.out.println(classes.getName());
		Set<Student> students = classes.getStudents();
		for (Student student : students) {
			System.out.println(student.getName());
		}
		session.close();
	}
	
	/**
	 * join  利用左外连接一条SQL语句把classes和student表全部查询出来了
	 * 
	 * 在含有子查询的需求分析中,利用join的抓取策略是不取的
	 * 1条sql
	 */
	@Test
	public void testQueryClassesByCidAndStudents_Join(){
		Session session = HibernateUtils.openSession();
		Classes classes = (Classes)session.get(Classes.class, 1L);//发出sql,故fetch为join的抓取,会导致懒加载的失效
		System.out.println(classes.getName());
		Set<Student> students = classes.getStudents();
		
		for (Student student : students) {
			System.out.println(student.getName());
		}
		session.close();
	}
}


总结:

因为抓取策略的设置在映射文件中,所以一旦映射文件生成就不能改变了。

通过发出SQL语句的不同的形式加载集合,从而优化效率的。

fetch为join的抓取策略会导致懒加载的失效

在设为join时,他会直接将从表信息以join方式查询到而不是再次使用select查询,这样导致了懒加载的失效。

抓取策略和延迟加载的结合

Set集合

1、 当fetch为join时,lazy失效

2、 当fetch为select时

如果lazy为true/extra

        当遍历集合的时候,发出加载集合的sql语句

如果lazy为false

        当获取班级的时候,发出加载集合的sql语句

3、 当fetch为subselect时和上面的情况一致。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值