Hibernate —— 理解fetch抓取策略

package me.ljm.hibernate.test;

import java.util.List;

import me.ljm.hibernate.entity.Classroom;
import me.ljm.hibernate.entity.Student;

import org.hibernate.Session;
import org.junit.Test;

/**
 * 抓取策略测试
 * @author ljm
 *
 */
public class FetchTest extends AbstractTest {
	
	/**
	 * 条件:
	 * 此时为xml的测试默认情况:fetch=select
	 * 我们来加载一个对象,且不导航关联对象
	 * 
	 * 结果:
	 * 一条语句,没有关联查询
	 * select student0_.id as id2_0_, student0_.name as name2_0_, student0_.sex as sex2_0_, 
	 *        student0_.cla_id as cla4_2_0_ from t_student student0_ where student0_.id=?
	 * @throws Exception
	 */
	@Test
	public void testSelectOnLoadAndNoNav() throws Exception {
		Session session = null;
		try {
			session = getSession();
			session.beginTransaction();
			
			Student stu = (Student)session.load(Student.class, 1);
			System.out.println(stu.getName());
			
			session.getTransaction().commit();
		} catch (Exception e) {
			session.getTransaction().rollback();
			e.printStackTrace();
		} finally {
			close(session);
		}
	}
	
	/**
	 * 条件:
	 * 此时为xml的另一种情况:fetch=join
	 * 我们来加载一个对象,且不导航关联对象
	 * 
	 * 结果:
	 * 一条SQL,关联查询
	 * select student0_.id as id2_2_, student0_.name as name2_2_, student0_.sex as sex2_2_, 
	 *        student0_.cla_id as cla4_2_2_, classroom1_.id as id1_0_, classroom1_.name as name1_0_, 
	 *        classroom1_.grade as grade1_0_, classroom1_.special_id as special4_1_0_, 
	 *        special2_.id as id0_1_, special2_.name as name0_1_, special2_.type as type0_1_ 
	 *  from t_student student0_ 
	 *  left outer join t_classroom classroom1_ on student0_.cla_id=classroom1_.id 
	 *  left outer join t_special special2_ on classroom1_.special_id=special2_.id
	 *   where student0_.id=?
	 * @throws Exception
	 */
	@Test
	public void testJoinOnLoadAndNoNav() throws Exception {
		Session session = null;
		try {
			session = getSession();
			session.beginTransaction();
			
			Student stu = (Student)session.load(Student.class, 1);
			System.out.println(stu.getName());
			
			session.getTransaction().commit();
		} catch (Exception e) {
			session.getTransaction().rollback();
			e.printStackTrace();
		} finally {
			close(session);
		}
	}

	/**
	 * 条件:
	 * 此时为xml的测试默认情况:fetch=select
	 * 我们来加载一个对象 ,导航关联对象
	 * 
	 * 结果:
	 * 发出3条SQL语句,不关联查询
	 * Hibernate: select student0_.id as id2_0_, student0_.name as name2_0_, 
	 *                   student0_.sex as sex2_0_, student0_.cla_id as cla4_2_0_ 
	 *              from t_student student0_ where student0_.id=?
     * Hibernate: select classroom0_.id as id1_0_, classroom0_.name as name1_0_, 
     *                   classroom0_.grade as grade1_0_, classroom0_.special_id as special4_1_0_ 
     *              from t_classroom classroom0_ where classroom0_.id=?
     * Hibernate: select special0_.id as id0_0_, special0_.name as name0_0_, 
     *                   special0_.type as type0_0_ 
     *              from t_special special0_ where special0_.id=?
     * 陈虎,计算机教育1班,计算机教育
	 * @throws Exception
	 */
	@Test
	public void testSelectOnLoadAndNav() throws Exception {
		Session session = null;
		try {
			session = getSession();
			session.beginTransaction();
			
			Student stu = (Student)session.load(Student.class, 1);
			System.out.println(stu.getName()+","+stu.getClassroom().getName()
					           +","+stu.getClassroom().getSpecial().getName());
			
			session.getTransaction().commit();
		} catch (Exception e) {
			session.getTransaction().rollback();
			e.printStackTrace();
		} finally {
			close(session);
		}
	}

	/**
	 * 条件:
	 * 此时为xml的另一种情况:fetch=join
	 * 我们来加载一个对象,导航关联对象
	 * 
	 * 结果:
	 * 发出一条SQL,关联查询
	 * Hibernate: select student0_.id as id2_2_, student0_.name as name2_2_, student0_.sex as sex2_2_,
	 *                   student0_.cla_id as cla4_2_2_, classroom1_.id as id1_0_, 
	 *                   classroom1_.name as name1_0_, classroom1_.grade as grade1_0_, 
	 *                   classroom1_.special_id as special4_1_0_, special2_.id as id0_1_, 
	 *                   special2_.name as name0_1_, special2_.type as type0_1_ 
	 *              from t_student student0_ 
	 *                   left outer join t_classroom classroom1_ on student0_.cla_id=classroom1_.id 
	 *                   left outer join t_special special2_ on classroom1_.special_id=special2_.id 
	 *             where student0_.id=?
     * 陈虎,计算机教育1班,计算机教育
	 * @throws Exception
	 */
	@Test
	public void testJoinOnLoadAndNav() throws Exception {
		Session session = null;
		try {
			session = getSession();
			session.beginTransaction();
			
			Student stu = (Student)session.load(Student.class, 1);
			System.out.println(stu.getName()+","+stu.getClassroom().getName()
					           +","+stu.getClassroom().getSpecial().getName());
			
			session.getTransaction().commit();
		} catch (Exception e) {
			session.getTransaction().rollback();
			e.printStackTrace();
		} finally {
			close(session);
		}
	}
	
	/**
	 * 条件:
	 * 此时为xml的测试默认情况:fetch=select
	 * 我们来列出所有对象 ,不导航关联对象
	 * 
	 * 结果:
	 * 一条SQL,不关联查询
	 * Hibernate: select student0_.id as id2_, student0_.name as name2_, student0_.sex as sex2_, 
	 *                   student0_.cla_id as cla4_2_ from t_student student0_
	 * @throws Exception
	 */
	@Test
	public void testSelectOnListAndNoNav() throws Exception {
		Session session = null;
		try {
			session = getSession();
			session.beginTransaction();
			
			List<Student> stus = session.createQuery("from Student").list();
			for (Student stu : stus) {
				System.out.println(stu.getName());
			}
			
			session.getTransaction().commit();
		} catch (Exception e) {
			session.getTransaction().rollback();
			e.printStackTrace();
		} finally {
			close(session);
		}
	}
	
	
	/**
	 * 条件:
	 * 此时为xml的另一种情况:fetch=join
	 * 我们来列出所有对象 ,不导航关联对象
	 * 
	 * 结果:
	 * 1条SQL,不关联查询
	 * Hibernate: select student0_.id as id2_, student0_.name as name2_, student0_.sex as sex2_,
	 *                   student0_.cla_id as cla4_2_ from t_student student0_
	 * @throws Exception
	 */
	@Test
	public void testJoinOnListAndNoNav() throws Exception {
		Session session = null;
		try {
			session = getSession();
			session.beginTransaction();
			
			List<Student> stus = session.createQuery("from Student").list();
			for (Student stu : stus) {
				System.out.println(stu.getName());
			}
			
			session.getTransaction().commit();
		} catch (Exception e) {
			session.getTransaction().rollback();
			e.printStackTrace();
		} finally {
			close(session);
		}
	}
	
	/**
	 * 条件:
	 * 此时为xml的测试默认情况:fetch=select
	 * 我们来列出所有对象 ,导航关联对象
	 * 
	 * 结果:
	 * 发出大量的SQL,延迟加载导致
	 * Hibernate: select student0_.id as id2_, student0_.name as name2_, student0_.sex as sex2_, 
	 *                   student0_.cla_id as cla4_2_ 
	 *              from t_student student0_ limit ?
     * Hibernate: select classroom0_.id as id1_0_, classroom0_.name as name1_0_, 
     *                   classroom0_.grade as grade1_0_, classroom0_.special_id as special4_1_0_ 
     *              from t_classroom classroom0_ where classroom0_.id=?
     * Hibernate: select special0_.id as id0_0_, special0_.name as name0_0_, 
     *                   special0_.type as type0_0_ 
     *              from t_special special0_ where special0_.id=?
     *              
     * Hibernate: select classroom0_.id as id1_0_, classroom0_.name as name1_0_, 
     *                   classroom0_.grade as grade1_0_, classroom0_.special_id as special4_1_0_ 
     *              from t_classroom classroom0_ where classroom0_.id=?     
     *              .....
     *              .....
     *              .....        
	 * @throws Exception
	 */
	@Test
	public void testSelectOnListAndNav() throws Exception {
		Session session = null;
		try {
			session = getSession();
			session.beginTransaction();
			
			List<Student> stus = session.createQuery("from Student")
					.setFirstResult(0).setMaxResults(200).list();
			for (Student stu : stus) {
				System.out.println(stu.getName()+","+stu.getClassroom()
						+","+stu.getClassroom().getSpecial());
			}
			
			session.getTransaction().commit();
		} catch (Exception e) {
			session.getTransaction().rollback();
			e.printStackTrace();
		} finally {
			close(session);
		}
	}
	
	/**
	 * 条件:
	 * 此时为xml的另一种情况:fetch=join
	 * 我们来列出所有对象 ,导航关联对象
	 * 
	 * 结果:
	 * 发出大量的SQL,延迟加载导致; 
	 * 和fetch=select不同的是,导航的第一个对象会延迟加载,导航的第二个对象会关联加载。所以相对来说SQL语句的数量少一些。
	 * 
	 * 结论:
	 * fetch=join作用:
	 * 1、在xml配置的情况中,
	 *    如果只得到Student列表,则和fetch=select的效果一样;解决方法是bitch-size 和 join fetch
	 *    如果要得到Student关联的Classroom,则会取出所有关联的对象,即使并未用到Special
	 * fetch=FetchType.EARGER(相当于fetch=join):
	 * 1、在annotation配置的情况下,
	 *    会取出所有的关联对象
	 * Hibernate: select student0_.id as id2_, student0_.name as name2_, student0_.sex as sex2_, 
	 *                   student0_.cla_id as cla4_2_ 
	 *              from t_student student0_ limit ?
     * Hibernate: select classroom0_.id as id1_1_, classroom0_.name as name1_1_, 
     *                   classroom0_.grade as grade1_1_, classroom0_.special_id as special4_1_1_, 
     *                   special1_.id as id0_0_, special1_.name as name0_0_, 
     *                   special1_.type as type0_0_ 
     *              from t_classroom classroom0_ 
     *                   left outer join t_special special1_ on classroom0_.special_id=special1_.id 
     *             where classroom0_.id=?  
     *             
     * Hibernate: select classroom0_.id as id1_1_, classroom0_.name as name1_1_, 
     *                   classroom0_.grade as grade1_1_, classroom0_.special_id as special4_1_1_, 
     *                   special1_.id as id0_0_, special1_.name as name0_0_, 
     *                   special1_.type as type0_0_ 
     *              from t_classroom classroom0_ 
     *                   left outer join t_special special1_ on classroom0_.special_id=special1_.id 
     *             lwhere classroom0_.id=?
     *              .....
     *              .....
     *              .....        
	 * @throws Exception
	 */
	@Test
	public void testJoinOnListAndNav() throws Exception {
		Session session = null;
		try {
			session = getSession();
			session.beginTransaction();
			
			/*List<Student> stus = session.createQuery("from Student")
					.setFirstResult(0).setMaxResults(200).list();
			for (Student stu : stus) {
				System.out.println(stu.getName()+","+stu.getClassroom()
						+","+stu.getClassroom().getSpecial());
			}*/
			List<Classroom> clas = session.createQuery("from Classroom").list();
			for (Classroom classroom : clas) {
				System.out.println(classroom.getName()+","+classroom.getSpecial());
			}
			
			session.getTransaction().commit();
		} catch (Exception e) {
			session.getTransaction().rollback();
			e.printStackTrace();
		} finally {
			close(session);
		}
	}
	
	@Test
	public void testFetchEqualsLazy() throws Exception {
		Session session = null;
		try {
			session = getSession();
			session.beginTransaction();
			
			List<Student> stus = session.createQuery("select stu from Student stu join stu.classroom").list();
			for (Student stu : stus) {
				System.out.println(stu.getName()+","+stu.getClassroom());
//				System.out.println(stu.getName());
			}
			
			session.getTransaction().commit();
		} catch (Exception e) {
			session.getTransaction().rollback();
			e.printStackTrace();
		} finally {
			close(session);
		}
	}
	
	/**
	 * 发出多条sql的最佳解决方案
	 * join fetch
	 * 但join fetch不能使用 select count(*)
	 * @throws Exception
	 */
	@Test
	public void testFetchSolution() throws Exception {
		Session session = null;
		try {
			session = getSession();
			session.beginTransaction();
			
			List<Student> stus = session.createQuery("select stu from Student stu left join fetch stu.classroom").list();
			for (Student stu : stus) {
				System.out.println(stu.getName()+","+stu.getClassroom());
			}
			
			session.getTransaction().commit();
		} catch (Exception e) {
			session.getTransaction().rollback();
			e.printStackTrace();
		} finally {
			close(session);
		}
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值