抓取策略是指咱們須要在關聯對象間進行導航的時候,Hibernate如何獲取關聯對象的策略。session
select抓取策略:當咱們查詢某個對象時,hibernate會另外發出一條select語句查詢與之關聯的實體或者集合,也就是說當咱們在關聯對象上設置了lazy=true,而且fetch=select的時候,咱們查詢時,會首先查詢該實體除關聯對象外的其餘屬性。只有咱們使用到該實體的關聯的對象時纔會另外發出一條select語句查詢關聯對象。app
注意:這個方式爲默認的抓取方式,在使用get/load方式或者使用hql語句查詢時都是有效的。測試
例如:fetch
映射配置代碼:ui
<hibernate-mapping package="com.yehuanhuan.pojo"> <class name="Grade" table="grade"> <id name="id" column="gra_id"> <generator class="native"></generator> </id> <property name="gradeName"></property> <set name="stuId" fetch="select" lazy="true"> <key column="gradeId"></key> <one-to-many class="Student"/> </set> </class> </hibernate-mapping> |
測試代碼:spa
@Test public void testFetch01(){ Configuration cfg = new Configuration().configure(); SessionFactory sf = cfg.buildSessionFactory(new StandardServiceRegistryBuilder().applySettings(cfg.getProperties()).build()); Session session = sf.openSession(); Transaction ts = session.beginTransaction(); String hql = "from Grade g where g.id=1"; Grade grade = (Grade) session.createQuery(hql).uniqueResult(); System.out.print("等級:"+grade.getGradeName()+" "+"成員:"); for(Student s:grade.getStuId()){ System.out.print(" "+s.getName()); } ts.commit(); session.close(); } |
join抓取策略:hibernate在select語句中經過left outer join 方法來獲取關聯實體或者實體集合的值,此時不管lazy的值是什麼,hibernate都會在查詢時當即把關聯對對象的值查詢出來。.net
注意:join抓取策略,只有在咱們使用get/load方式查詢時有效,而使用hql語句查詢時無效。hibernate
我的認爲緣由:對象
使用hql語句的時候hibernate是直接讀取hql語句進行查詢,而hql語句中並無join鏈接關聯對象,而使用get/load方式的時候是hibernate讀取完配置文件以後拼寫的hql語句,這裏已經知道咱們配置了fetch,因此會加上join。ci
例如:
測試代碼:
@Test public void testFetch01(){ Configuration cfg = new Configuration().configure(); SessionFactory sf = cfg.buildSessionFactory(new StandardServiceRegistryBuilder().applySettings(cfg.getProperties()).build()); Session session = sf.openSession(); try{ Transaction ts = session.beginTransaction(); Grade grade = (Grade) session.load(Grade.class, 1); System.out.print("等級:"+grade.getGradeName()+" "+"成員:"); for(Student s:grade.getStuId()){ System.out.println(" "+s.getName()); } ts.commit(); }catch (Exception e) { // TODO: handle exception e.printStackTrace(); }finally { session.close(); } } |
映射配置代碼:
<hibernate-mapping package="com.yehuanhuan.pojo"> <class name="Grade" table="grade"> <id name="id" column="gra_id"> <generator class="native"></generator> </id> <property name="gradeName"></property> <set name="stuId" fetch="join" lazy="true"> <key column="gradeId"></key> <one-to-many class="Student"/> </set> </class> </hibernate-mapping> |
subselect抓取策略:當咱們查詢某個對象時,hibernate會另外發出一條select語句查詢與前面查詢關聯的全部的集合,與select抓取策略不一樣的是當咱們用到一個關聯對象的時候,hibernate會把前面查詢出來的實體相關聯的集合所有查詢出來,而select策略查詢的時候是用到前面查詢的哪一個對象的關聯對象,就查詢哪一個對象的關聯實體。
注意:subselect抓取策略在使用get/load方式或者使用hql語句查詢時都是有效的。這時候lazy只是影響咱們查詢關聯對象集合的時機。只有在一對多的一端或者多對多的狀況下,纔有subselect抓取策略。在一對多的多端沒有subselect抓取策略。
例如:
映射配置代碼:
<hibernate-mapping package="com.yehuanhuan.pojo"> <class name="Grade" table="grade"> <id name="id" column="gra_id"> <generator class="native"></generator> </id> <property name="gradeName"></property> <set name="stuId" fetch="subselect" lazy="true"> <key column="gradeId"></key> <one-to-many class="Student"/> </set> </class> |
測試代碼:
@Test public void testFetch01(){ Configuration cfg = new Configuration().configure(); SessionFactory sf = cfg.buildSessionFactory(new StandardServiceRegistryBuilder().applySettings(cfg.getProperties()).build()); Session session = sf.openSession(); try{ Transaction ts = session.beginTransaction(); List<Grade> results = session.createCriteria(Grade.class).add(Restrictions.in("id", new Integer[]{1,2})).list(); for(Grade g:results){ System.out.print("等級:"+g.getGradeName()+" "+"成員:"); for(Student s:g.getStuId()){ System.out.print(" "+s.getName()); } System.out.println(); } ts.commit(); }catch (Exception e) { // TODO: handle exception e.printStackTrace(); }finally { session.close(); } } |
解釋:這個測試代碼當程序走到for(Student s:g.getStuId())裏的時候hibernate會查詢id=1和id=2的關聯對象的信息。而若是是select抓取策略則是循環第二輪的時候纔會查詢id=2關聯的對象信息,也就是id=1和id=2關聯對象的信息是經過兩條select語句查詢的。