zoukankan      html  css  js  c++  java
  • Hibernate学习笔记(八) — 懒载入与抓取策略

    懒载入(Load On Demand)是一种独特而又强大的数据获取方法,它可以在用户滚动页面的时候自己主动获取很多其它的数据,而新得到的数据不会影响原有数据的显示,同一时候最大程度上降低server端的资源耗用。总结一句话:什么时候须要数据。什么时候载入。

    一、懒载入

    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时和上面的情况一致。

  • 相关阅读:
    性能测试监控指标-数据库
    cpu 故障定位
    ubuntu安装boost
    固定IP下虚拟机网卡配置及ssh
    零基础天池新闻推荐初学-04-排序模型+模型融合的简单学习(TODO 待进一步完善)
    零基础天池新闻推荐初学-04-特征工程(制作特征列和标签列,转为监督学习)
    零基础天池新闻推荐初学-03-多路召回
    零基础天池新闻推荐初学-02-数据分析
    零基础天池新闻推荐初学-01-赛题理解&Baseline
    初学推荐系统-06- GBDT+LR模型
  • 原文地址:https://www.cnblogs.com/yjbjingcha/p/6917453.html
Copyright © 2011-2022 走看看