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的懒加载)

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

总结

懒加载是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查询,这样导致了懒加载的失效。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-25 08:48:21

Hibernate学习笔记(八) — 懒加载与抓取策略的相关文章

thinkphp学习笔记9—自动加载

1.命名空间自动加载 在3.2版本中不需要手动加载类库文件,可以很方便的完成自动加载. 系统可以根据类的命名空间自动定位到类库文件,例如定义了一个类Org\Util\Auth类: namespace Org\Util; class Auth { } 保存到ThinkPHP/Library/Org/Util/Auth.class.php 这样我们就可以直接实例化了, new \Org\Util\Auth(); 实例化之后系统会自动加载 ThinkPHP/Library/Org/Util/Auth.

《Hibernate学习笔记八》:组件映射

<Hibernate学习笔记八>:组件映射 前面介绍了一对一的单向.双向外键关联,例如,学生证和学生是一个一对一的关系.这篇博文主要是介绍下组件映射,即一个是另一个的一部分,例如,学生证的信息也可以作为学生信息的一部分,即在数据库中只存在学生一个表,而不是有学生和学生证两个表,并且这两个表中有一个一对一的关联关系. 如下: 有人或许会说,那我们就将学生和学生证的信息写在一个类中,则就不需要组件映射了,确实可以这样,但是,根据类的设计原则,我们一般都会将其设计为两个类,然后将学生证的信息作为一个

虚拟机VMWare学习笔记十二 - 将物理机抓取成虚拟机

1. 安装VMware vCenter Converter Standalone Client 运行虚拟机,File -- Virtualize a Physical Machine 这时如果电脑中没有VMware vCenter Converter Standalone Client ,则会进行安装. 安装过程 之后图标会出现在桌面上,双击运行 选择连接到本地服务器,登陆 点击转换计算机 这个,可以将本地计算机抓取成虚拟机,也可以将其他可以访问的计算机(需知道管理员用户名及密码)抓取成虚拟机.

Hibernate get对象的懒加载问题

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.wolf.a_StudentManageSystem.domain.Teacher.courses, could not initialize proxy - no Session at org.hibernate.collection.internal.AbstractPersistentCollect

Hibernate中的延迟加载(懒加载)

什么是懒加载? Hibernate提供了一种机制,即在设置了使用懒加载的情况下,查询某一条数据时不会立即访问数据库,因此不会返回指定对象,而是返回代理对象,该代理对象并不为null,它实际上是Hibernate自动实现的指定对象所属类的子类的对象,该对象具有默认值.当要使用真正对象的属性的时候才会访问数据库,这时代理对象会自动查询数据库中对应对象的数据并返回. 这样一来降低了程序对数据库访问次数和内存使用量.下面我们通过懒加载适用情况分析它究竟是如何做到的. 懒加载的适用情况? 1.获取某一个对

hibernate学习(6)——加载策略(优化)

1. 检索方式 1  立即检索:立即查询,在执行查询语句时,立即查询所有的数据. 2 延迟检索:延迟查询,在执行查询语句之后,在需要时在查询.(懒加载) 2.  检查策略 1  类级别检索:当前的类的属性获取是否需要延迟. 2  关联级别的检索:当前类 关联 另一个类是否需要延迟. 3.类级别检索 1  get:立即检索.get方法一执行,立即查询所有字段的数据. 2 load:延迟检索.默认情况,load方法执行后,如果只使用OID的值不进行查询,如果要使用其他属性值将查询 . Custome

Hibernate 性能优化之懒加载

针对数据库中的大数据,不希望特别早的加载到内存中,当用到它的时候才加载 懒加载分为:类的懒加载.集合的懒加载.单端关联的懒加载 类的懒加载    1.在默认情况下,类就是执行懒加载        2.只有使用了load方法以后才能用懒加载    3.如果在相应的映射文件中,设置<class>的lazy="false"懒加载将失去效果集合的懒加载     1.针对一多对的情况或者多对多的情况    2.根据一方加载set集合,决定在什么时候给set集合填充数据        

Hibernate(九)__OpenSessionInView解决懒加载问题

什么是OpenSessionInView? 在hibernate中使用load方法时,并未把数据真正获取时就关闭了session,当我们真正想获取数据时会迫使load加载数据,而此时session已关闭,所以就会出现异常. 比较典型的是在MVC模式中,我们在M层调用持久层获取数据时(持久层用的是load方法加载数据),当这一调用结束时,session随之关闭,而我们希望在V层使用这些数据,这时才会迫使load加载数据,我们就希望这时的session是open着得,这就是所谓的Open Sessi

ExtJS学习笔记3:加载、提交和验证表单

加载数据 1.比较好用的设置form数据的方法: formPanel.getForm().setValues([{id: 'FirstName', value: 'Joe'}]); 其中id值为form中field的name属性值,value为要赋的值 2.通过对象赋值: Ext.define('Request', { extend: 'Ext.data.Model', fields: [ 'FirstName', 'LastName', 'EmailAddress', 'TelNumberCo