Hibernate(四)

来源:互联网 发布:泽东书法 知乎 编辑:程序博客网 时间:2024/05/16 05:09

抓取策略

案例一

<!--默认值为”select” --><set name="students" lazy="true" fetch="select">
/**     * 发出两条sql语句     */    @Test    public void testSetFetch_Select(){        Session session = sessionFactory.getCurrentSession();        Transaction transaction = session.beginTransaction();        Classes classes = (Classes)session.get(Classes.class, 1L);        Set<Student> students = classes.getStudents();        for(Student student:students){            System.out.println(student.getName());        }        transaction.commit();    }

fetch_select

上述的图中会发出n+1条sql语句,1代表查询classes表的数据,n代表classes表中的记录数

Hibernate:     select        classes0_.cid as cid0_0_,        classes0_.name as name0_0_     from        Classes classes0_     where        classes0_.cid=?Hibernate:     select        students0_.cid as cid0_1_,        students0_.sid as sid1_,        students0_.sid as sid1_0_,        students0_.name as name1_0_,        students0_.cid as cid1_0_     from        Student students0_     where        students0_.cid=?

案例二

<set name="students" lazy="true" fetch="join">
Hibernate:     select        classes0_.cid as cid0_1_,        classes0_.name as name0_1_,        students1_.cid as cid0_3_,        students1_.sid as sid3_,        students1_.sid as sid1_0_,        students1_.name as name1_0_,        students1_.cid as cid1_0_     from        Classes classes0_     left outer join        Student students1_             on classes0_.cid=students1_.cid     where        classes0_.cid=?

案例三

<set name="students" lazy="true" fetch="subselect">
/**     *  查询所有的班级的所有的学生     */    @Test    public void testSubSelect(){        Session session = sessionFactory.getCurrentSession();        Transaction transaction = session.beginTransaction();        List<Classes> classesList = session.createQuery("from Classes").list();        for(Classes classes:classesList){            Set<Student> students = classes.getStudents();            for(Student student:students){                System.out.println(student.getName());            }        }        transaction.commit();    }
Hibernate:     select        classes0_.cid as cid0_,        classes0_.name as name0_     from        Classes classes0_Hibernate:     select        students0_.cid as cid0_1_,        students0_.sid as sid1_,        students0_.sid as sid1_0_,        students0_.name as name1_0_,        students0_.cid as cid1_0_     from        Student students0_     where        students0_.cid in (            select                classes0_.cid             from                Classes classes0_        )

案例四

/**     * 查询cid为1,2,3的班级的信息和这些班级中学生的信息     */    @Test    public void testSubSelect_2(){        Session session = sessionFactory.getCurrentSession();        Transaction transaction = session.beginTransaction();        List<Classes> classesList = session.createQuery("from Classes where cid in(1,2,3)").list();        for(Classes classes:classesList){            Set<Student> students = classes.getStudents();            for(Student student:students){                System.out.println(student.getName());            }        }        transaction.commit();    }
Hibernate:     select        classes0_.cid as cid0_,        classes0_.name as name0_     from        Classes classes0_     where        classes0_.cid in (            1 , 2 , 3        )Hibernate:     select        students0_.cid as cid0_1_,        students0_.sid as sid1_,        students0_.sid as sid1_0_,        students0_.name as name1_0_,        students0_.cid as cid1_0_     from        Student students0_     where        students0_.cid in (            select                classes0_.cid             from                Classes classes0_             where                classes0_.cid in (                    1 , 2 , 3                )        )

总结
需要一次性把数据全部查询出来,用join
如果经过需求分析翻译出来有子查询,用subselect
默认情况下用select
抓取策略的研究前提必须是关联对象,是研究怎么样发出sql语句来提取数据的
抓取策略只不过是hibernate给大家提供的一种优化策略而已。
因为抓取策略是写在映射文件中的,所以只能写一次。如果要想改变sql语句的结构,则用hql语句。
Subselect可以防止n+1条sql语句的出现

抓取策略和懒加载
1、研究对象为set集合
2、如果抓取策略为join,则懒加载失效
3、如果抓取策略为select,则保持懒加载的策略
4、如果抓取策略为subselect,则保持懒加载的策略

二级缓存
概念
1、为sessionFactory级别的缓存
2、二级缓存存放的是公共的数据
3、二级缓存的生命周期和sessionFactory的生命周期一样
4、二级缓存的存和取的策略

二级缓存

把数据存放到二级缓存中

Get方法

@Test    public void testGet(){        Session session = sessionFactory.openSession();        Classes classes = (Classes)session.get(Classes.class, 2L);        System.out.println(sessionFactory.getStatistics().getEntityLoadCount());        session.close();        session = sessionFactory.openSession();        classes = (Classes)session.get(Classes.class, 2L);        session.close();    }
Hibernate:     select        classes0_.cid as cid0_0_,        classes0_.name as name0_0_     from        Classes classes0_     where        classes0_.cid=?

只发出了一条sql语句,第二个session.get方法的对象来自于二级缓存
2、当session执行save或者update方法的时候,没有必要放入到二级缓存中,因为修改的因素很大。

二级缓存的统计机制

<!--         开启hibernate的统计机制     -->     <property name="hibernate.generate_statistics">true</property>

二级缓存的特点
一般情况下把一个对象放入到二级缓存中,对象的属性一般是不会改变的。

RW

RO

利用CacheModel控制二级缓存的对象
cacheModel

Hibernate:     select        classes0_.cid as cid0_0_,        classes0_.name as name0_0_     from        Classes classes0_     where        classes0_.cid=?1Hibernate:     update        Classes     set        name=?     where        cid=?222

二级缓存的磁盘化

<diskStore path="e:\\TEMP1"/>            <Cache            name="cn.itcast.sh08.hibernate.domain.Classes"            maxElementsInMemory="3"             eternal="false"            timeToIdleSeconds="120"            timeToLiveSeconds="120"            overflowToDisk="true"            maxElementsOnDisk="10000000"            diskPersistent="false"            diskExpiryThreadIntervalSeconds="120"            memoryStoreEvictionPolicy="LRU"            />

二级缓存磁盘化

0 0
原创粉丝点击