Hibernate中的抓取策略

抓取策略是指咱們須要在關聯對象間進行導航的時候,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語句查詢的。

相關文章
相關標籤/搜索