Hibernate框架4

内容

   Hibernate的二级缓存

   Hibernate的查询缓存

内容回顾:

Hibernate的检索方式:

        * 对象导航方式:

                * Customer customer = ...;

                * customer.getOrders(); 

        * 根据OID进行检索:

                * get();

                * load();

        * HQL:

                * session.createQuery(“HQL”);

                * 简单查询:

                        * from Customer;

                * 排序查询:

                         * from Cusomer order by 属性;

                * 条件查询:

                        * 位置绑定:

                                * from Customer where cname = ?;

                        * 名称绑定:

                                * from Customer where cname = :aaa;

                * 分页查询:

                        * query.setFirstResult(0);

                        * query.setMaxResults(10);

                * 聚集函数:

                        * select count(*) from Customer;

                * 多态查询:

                * 别名查询:

                * 构造方法:

                * 投影查询:

                * 多表查询:

                * 交叉连接:

                        * 内连接:

                        * 迫切内连接:

                        * 左外连接:

                        * 迫切左外连接:

                * 命名查询:

        * QBC:

                * session.createCriteria(Class clazz);

                * 简单查询:

                * 排序查询:

                * 条件查询:

                * 分页查询:

                * 离线条件查询:

        * SQL:

                * session.createSQLQuery(“SQL”);

* Hibnerate的抓取策略:

        * 立即检索:

        * 延迟检索:

                * 在<class>设置lazy=”false”

                * 在持久化类上设置final.(立即检索)

                * 在调用方法的时候,初始化代理对象.

        * 延迟的时候:

                * 类级别延迟:

                        * <class>标签上lazy

               *关联级别延迟:

                        * <set>/<many-to-one>/<one-to-one>

                * fetch和lazy配置:

                * <set>

                        * fetch:

                                * select :默认值:

                                * join   :使用迫切左外连接的形式.

                                * subselect:使用子查询查询的关联对象.

                        * lazy:

                                * true   :默认值

                                * false  :不采用延迟.

                                * extra  :及其懒惰.

                * <many-to-one>

                        * fetch  :

                                * select :默认值.

                                * join   :使用迫切左外连接

                        * lazy   :

                                * proxy  :是否采用延迟看另一方<class>标签上配置的lazy是什么.

                                * false  :不采用延迟

                                * no-proxy

                    * batch-size:批量抓取.

* Hibernate中事务与并发:

        * 事务管理:

                * 特性:

                * 隔离级别:

                * 丢失更新解决:

        * Hibernate中事务并发管理:

                * 设置隔离级别:

                * 使用悲观锁和乐观锁解决丢失更新:

                * 提供了本地线程绑定session:

* Hibernate的二级缓存:

        * 二级缓存:SessionFactory级别缓存.可以在多个session之间共享数据的.

        * 二级缓存结构:

                * 类缓存区,集合缓存区,更新时间戳,查询缓冲区.

        * 二级缓存的适合放入的数据:

                * 不经常修改的,允许偶尔出现并发问题.

        * 二级缓存的配置:

                * 在Hibernate中开启二级缓存.

                * 配置二级缓存的提供商:

                        * EHCache

                * 配置哪些类使用二级缓存:

                        * 在映射文件中配置.

                        * 在核心配置文件中配置(推荐).

1.2   Hibernate的二级缓存:

缓存(Cache):计算机领域非常通用的概念。它介于应用程序和永久性数据存储源(如硬盘上的文件或者数据库)之间,其作用是降低应用程序直接读写永久性数据存储源的频率,从而提高应用的运行性能。缓存中的数据是数据存储源中数据的拷贝。缓存的物理介质通常是内存

Hibernate中提供了两个级别的缓存
        • 第一级别的缓存是 Session 级别的缓存,它是属于 事务范围的缓存 。这一级别的缓存由 hibernate 管理的,一般情况下无需进行干预
        • 第二级别的缓存是 SessionFactory 级别的缓存,它是属于 进程范围的缓存
Hibernate的缓存可以分为两类:
        • 内置缓存 : Hibernate 自带的 , 不可卸载 . 通常在 Hibernate 的初始化阶段 ,Hibernate 会把映射元数据和预定义的 SQL 语句放到 SessionFactory 的缓存中 , 映射元数据是映射文件中数据的复制 , 而预定义 SQL 语句时 Hibernate 根据映射元数据推到出来的 . 该内置缓存是 只读的.
        • 外置缓存 ( 二级缓存 ) : 一个可配置的缓存插件 . 在默认情况下 , SessionFactory 不会启用这个缓存插件 . 外置缓存中的数据是数据库数据的复制 , 外置缓存的物理介质可以是内存或硬盘

hibernate二级缓存的结构


二级缓存的并发访问策略


缓存中存放的数据
适合放入二级缓存中的数据 :
        • 很少被修改
        • 不是很重要的数据 , 允许出现偶尔的并发问题
不适合放入二级缓存中的数据 :
        • 经常被修改
        • 财务数据 , 绝对不允许出现并发问题

        与其他应用数据共享的数据

缓存提供的供应商

Hibernate 的二级缓存是进程或集群范围内的缓存 , 缓存中存放的是对象的散装数据
二级缓存是可配置的的插件 ,Hibernate 允许选用以下类型的缓存插件 :
        • EHCache : 可作为进程范围内的缓存 , 存放数据的物理介质可以是内存或硬盘 , Hibernate查询缓存提供了支持
        • OpenSymphony `: 可作为进程范围内的缓存 , 存放数据的物理介质可以是内存或硬盘 , 提供了丰富的缓存数据过期策略, Hibernate 的查询缓存提供了支持
        • SwarmCache : 可作为集群范围内的缓存 , 但不支持 Hibernate的查询缓存
        • JBossCache : 可作为集群范围内的缓存 , 支持 Hibernate的查询缓存

4 种缓存插件支持的并发访问策略(x 代表支持, 空白代表不支持)


配置进程范围内的二级缓存(配置ehcache缓存)

1 拷贝ehcache-1.5.0.jar到当前工程的lib目录下

        依赖backport-util-concurrent commons-logging

2 开启二级缓存

   <property name="hibernate.cache.use_second_level_cache">true</property>

3 要指定缓存的供应商

   <property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>

4 指定使用二级缓存的类

    * 方法一 在使用类的*.hbm.xml配置

选择需要使用二级缓存的持久化类 , 设置它的二级缓存的并发访问策略 ,<class> 元素的 cache 子元素表明 Hibernate 会缓存对象的简单属性 , 但不会缓存集合属性 , 若希望缓存集合属性中的元素 , 必须在 <set> 元素中加入 <cache> 子元素


*方法二  在hibernate.cfg.xml文件中配置(建议)

      <!-- 指定使用二级缓存的类放在maping下面 -->

      <!-- 配置类级别的二级缓存-->

      <class-cache class="cn.itcast.c3p0.Customer" usage="read-write"/>

      <class-cache class="cn.itcast.c3p0.Order" usage="read-write"/>

    <!-- 配置集合级别的二级缓存-->

    <collection-cache collection="cn.itcast.c3p0.Customer.orders" usage="read-write"/>

5 配置ehcache默认的配置文件ehcache.xml(名字固定)(放在类路径下)


一级缓存:缓存地址,下次在做get的时候,会从一级缓存中获取。第一条打出:true

二级缓存:缓存的是散装数据(每个数据拿出来放在二级缓存里),在获取的时候,因为一级生命周期结束,从二级缓存中获取,又会得到一个对象,把数据拿出来,重新组装成一个Customer对象,相当于Customer c2=…,所以第二条得到的是false。

1.2.1    类缓存区特点:

缓存的是对象的散装的数据.

1.2.2    集合缓存区的特点:

缓存的是对象的id.需要依赖类缓冲区的配置.


若没有配置类缓存区,就会往集合区缓存数据,就会缓存的都是对象(订单)的id,再去查询,从二级缓存获取数据,再次用订单,从集合中获取id,发送根据id去查询的sql语句。集合缓存区的使用需要依赖类缓存区。

配置类缓存,好处:可以直接从二级缓存区获取数据。

<!-- Hibernate中开启二级缓存 -->
<property name="hibernate.cache.use_second_level_cache">true</property>
<!-- 配置二级缓存的提供商 -->

<property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>

<!-- 配置哪些类使用二级缓存 -->
<class-cache usage="read-write" class="cn.itcast.hibernate3.demo1.Customer"/>
<class-cache usage="read-write" class="cn.itcast.hibernate3.demo1.Order"/>
<!-- 集合缓冲区 -->

<collection-cache usage="read-write" collection="cn.itcast.hibernate3.demo1.Customer.orders"/>

测试类级别的二级缓存只适用于getload获取数据,对query接口可以将数据放置到类级别的二级缓存中,但是不能使用query接口的 list方法从缓存中获取数据;query接口将查询的对象放置到二级缓存的查询缓存

<!-- 配置查询缓存 -->

<property name="hibernate.cache.use_query_cache">true</property>

一级缓存更新数据会同步到二级缓存

二级缓存的数据存放到临时目录


配置进程范围内的二级缓存(配置ehcache缓存)

< diskStore >: 指定一个目录 , EHCache 把数据写到硬盘上时 , 将把数据写到这个文件目录下 .  默认是 C:\WINDOWS\Temp
< defaultCache >: 设置缓存的默认数据过期策略
< cache > 设定具体的命名缓存的数据过期策略

        使用name属性,cn.itcast.second.Order

每个命名缓存代表一个缓存区域,每个缓存区域有各自的数据过期策略。命名缓存机制使得用户能够在每个类以及类的每个集合的粒度上设置数据过期策略。 
cache元素的属性   
        • name : 设置缓存的名字 , 它的取值为类的全限定名或类的集合的名字
        • maxElementsInMemory : 设置基于内存的缓存中可存放的对象最大数目
        • eternal : 设置对象是否为永久的 ,true 表示永不过期 , 此时将忽略 timeToIdleSeconds timeToLiveSeconds 属性 ; 默认值是 false
        • timeToIdleSeconds : 设置对象空闲最长时间 , 以秒为单位 , 超过这个时间 , 对象过期。当对象过期时 , EHCache 会把它从缓存中清除。如果此值为 0,表示对象可以无限期地处于空闲状态。
        • timeToLiveSeconds : 设置对象生存最长时间 , 超过这个时间 , 对象过期。
如果此值为
0, 表示对象可以无限期地存在于缓存中 . 该属性值必须大于或等于 timeToIdleSeconds 属性值
        • overflowToDisk : 设置基于内在的缓存中的对象数目达到上限后 , 是否把溢出的对象写到基于硬盘的缓存中
        • diskPersistent jvm 结束时是否持久化对象 true false 默认是 false
        • diskExpiryThreadIntervalSeconds 指定专门用于清除过期对象的监听线程的轮询时间
       •   memoryStoreEvictionPolicy - 当内存缓存达到最大,有新的 element 加入的时候, 移除缓存中 element 的策略。默认是 LRU (最近最少使用),可选的有 LFU (最不常使用)和 FIFO (先进先出)

ehcache.xml文件

<diskStore path="D:\cache" />

<cache name=""  

           maxElementsInMemory="10“ 

           eternal=“true"

           overflowToDisk="true“

           maxElementsOnDisk=“10000000”

           diskPersistent="false“

           diskExpriyThreadIntervalSeconds=“120”/>

</ehcache>


查询所有.Query接口的list()方法.
 list()方法会向二级缓存中放数据,但是不会使用二级缓存中的数据.(一级缓存效率高,二级缓存效率低)
iterate()方法可以查询所有信息.
iterate方法会发送N+1条SQL查询(效率较低).但是会使用二级缓存的数据(用二级缓存时效率较高)

iterator 先到数据库中检索符合条件的id,然后根据id分别到一级和二级缓冲中查找对象 (没有在查询数据库,每次只能查一个,可能导致n+1次查询 )

Query接口的 iterate()方法
        • list() 一样也能执行查询操作
        • list() 方法执行的 SQL 语句包含实体类对应的数据表的所有字段
        • Iterate()方法执行的SQL 语句中仅包含实体类对应的数据表的ID 字段
        • 当遍历访问结果集时 , 该方法先到 Session 缓存及二级缓存中查看是否存在特定 OID 的对象 , 如果存在 , 就直接返回该对象 , 如果不存在该对象就通过相应的 SQLSelect 语句到数据库中加载特定的实体对象
大多数情况下 , 应考虑使用 list() 方法执行查询操作 .iterate() 方法仅在满足以下条件的场合, 可以稍微提高查询性能:
         •要查询的数据表中包含大量字段
        •启用了二级缓存, 且二级缓存中可能已经包含了待查询的对象

1.2.3    二级缓存数据到硬盘:

1.2.4    更新时间戳区域:

时间戳缓存区域

Hibernate 提供了和查询相关的缓存区域 :
        • 时间戳缓存区域 : org.hibernate.cahce. UpdateTimestampCache
时间戳缓存区域存放了对于查询结果相关的表进行插入 , 更新或删除操作的时间戳 .  Hibernate 通过时间戳缓存区域来判断被缓存的查询结果是否过期 , 其运行过程如下 :
        • T1 时刻执行查询操作 , 把查询结果存放在 QueryCache 区域 , 记录该区域的时间戳为 T1
        • T2 时刻对查询结果相关的表进行更新操作 ,Hibernate T2 时刻存放在 UpdateTimestampCache 区域 .
        • T3 时刻执行查询结果前 , 先比较 QueryCache 区域的时间戳和 UpdateTimestampCache 区域的时间戳 , T2>T1, 那么就丢弃原先存放在 QueryCache 区域的查询结果 , 重新到数据库中查询数据 , 再把结果存放到 QueryCache 区域 ; T2< T1, 直接从 QueryCache 中获得查询结果

注意:不能使用set的方式更新数据,因为set的方式清理session的一级缓存和二级缓存没有关系

1.2.5    查询缓存:

对于经常使用的 查询语句 , 如果启用了查询缓存 , 当第一次执行查询语句时 ,Hibernate 会把查询结果存放在查询缓存中 . 以后再次执行该查询语句时 , 只需从缓存中获得查询结果 , 从而提高查询性能
查询缓存使用于如下场合:
        • 应用程序运行时经常使用查询语句
        • 很少对与查询语句检索到的数据进行插入 , 删除和更新操作
使用查询缓存的步骤
        • 配置二级缓存 , 因为查询缓存依赖于二级缓存
        • hibernate 配置文件中启用查询缓存

              <property name=“hibernate.cache.use_query_cache">true</property>

        • 对于希望启用查询缓存的查询语句 , 调用 Query setCacheable (true) 方法
         查询某些字段时,要用到查询缓存

查询缓存可以缓存属性!!!!

比二级缓存功能更加强大,而且查询缓存必须依赖二级缓存.

二级缓存:对类/对象的缓存.

查询缓存:针对类中属性的缓存.

查询缓存的配置:

        * 配置查询缓存:(二级缓存已经配置完毕.)

        * 在核心配置文件中:

                <!-- 配置查询缓存 -->

                <property name="hibernate.cache.use_query_cache">true</property>

            * 编写代码的时候:

@Test
// 查询缓存的测试
public void demo9(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
Query query = session.createQuery("select c.cname from Customer c");

                /*
             * 设置查询缓存
        *    * 如果查询缓存存在 直接返回
         *    * 如果查询缓存不存在 查询数据库 将查询结果放置到查询缓存中
         */

// 使用查询缓存:

query.setCacheable(true);//发送
query.list();
tx.commit();
session = HibernateUtils.getCurrentSession();
tx = session.beginTransaction();
query = session.createQuery("select c.cname from Customer c");
query.setCacheable(true);//不发送aql
query.list();
tx.commit();

}

Myeclipse,可反向生成工程:新建一个项目,提供一个表,持久化类、映射文件和dao可以自动生成,但整合的时候有问题

1.3   Struts2和Hibernate的整合:

1.3.1    SH的整合

第一步:创建一个web项目:

第二步:导入jar包:

Struts2开发包:

Hibernate开发包:

        * hibernate3.jar

        * lib/jpa/*.jar

        * lib/required/*.jar

* mysql驱动

* c3p0

引入配置文件:

        * struts.xml

        * hibernate.cfg.xml

        * log4j.properties

第三步:创建包结构:

cn.itcast.vo

...

第四步:创建实体类与映射:

第五步:请求

customer_findAll.action

猜你喜欢

转载自blog.csdn.net/qq_24140237/article/details/79783444