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语句查询的。

相关文章
相关标签/搜索