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);
		}
	}
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章