转载:Hibernate + JPA @Cache .

先了解一下cache基础:

一级缓存

Hibernate 的一级缓存是由 Session 提供的,因此它只存在于 Session 的生命周期中,当程序调用 save(),update(),saveorupdate() 等方法 及调用查询接口 list,filter,iterate 时,如 session 缓存中还不存在相应的对象, Hibernate 会把该对象加入到一级缓存中,

当Session关闭的时候该Session所管理的一级缓存也会立即被清除

Hibernate的一级缓存是Session所内置的,不能被卸载,也不能进行任何配置

二级缓存配置

1 、首先要打开二级缓存,在 hibernate.cfg.xml 中添加如下配置:    

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

2、Hibernate的二级缓存使用第三方的缓存工具来实现,所以我们需要指定Hibernate使用哪个

缓存工具。如下配置指定Hibernate使用EhCache缓存工具。

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

3、Hibernate在默认情况下并不会对所有实体对象进行缓存,所以,我们需要指定缓存哪些对象,

在实体对象的映射文件中(相应的<class>标签内部),添加如下配置:

<cacheusage="read-only"/>

usage="read-only"是“只读”缓存策略。

注意,这个<cache>标签只能放在<class>标签的内部,而且必须处在<id>标签的前面!!!

这个<cache>标签放在哪些<class>标签下面,就说明会多这些类的对象进行缓存

4、对于第3步,有一个可选的方案是在hibernate.cfg.xml文件中指定哪些类的对象需要缓存,

而不需要使用<cache>标签来指定。如:

在hibernate.cfg.xml中添加如下配置:

<class-cacheclass="com.bjsxt.hibernate.Classes"usage="read-only"/>

注意,这个<class-cache>标签必须放在<mapping>标签的后面!!

Hibernate缓存配置

_____________________________________________________________________________________

Hibernate的缓存分为:

一级缓存:在Session级别的,在Session关闭的时候,一级缓存就失效了。

二级缓存:在SessionFactory级别的,它可以使用不同的缓存实现,如EhCache、JBossCache、OsCache等。

缓存的注释写法如下,加在Entity的java类上:

@Cache(usage=CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)

缓存的方式有四种,分别为:

CacheConcurrencyStrategy.NONE

CacheConcurrencyStrategy.READ_ONLY,只读模式,在此模式下,如果对数据进行更新操作,会有异常;

CacheConcurrencyStrategy.READ_WRITE,读写模式在更新缓存的时候会把缓存里面的数据换成一个锁,其它事务如果去取相应的缓存数据,发现被锁了,直接就去数据库查询;

CacheConcurrencyStrategy.NONSTRICT_READ_WRITE,不严格的读写模式则不会的缓存数据加锁;

CacheConcurrencyStrategy.TRANSACTIONAL,事务模式指缓存支持事务,当事务回滚时,缓存也能回滚,只支持JTA环境。

另外还有如下注意事项:

1、查询缓存需要在Query的相应方法执行前加上这么一句:

query.setCacheable(true);

在使用Hibernate时,获得的query有setCacheable方法,可以设置使用缓存,但当使用JPA时,javax.persistence.Query并没有setCacheable方法,此时如果JPA的实现是Hibernate时,可以将其进行如下转化,再调用setCacheable方法(如果JPA的实现是其它ORMAP框架,就不知道怎么做了)。

if (query instanceof org.hibernate.ejb.QueryImpl) {

 ((org.hibernate.ejb.QueryImpl) query).getHibernateQuery().setCacheable(true);

}

2、还有就是查询缓存的查询执行后,会将查询结果放入二级缓存中,但是放入的形式是以ID为Key,实例作为一个Value。

3、hibernate的配置文件中需加入如下信息:

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

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

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

  缓存映射(Cache mappings)

类或者集合映射的“<cache> 元素”可以有下列形式:

<cache usage="transactional|read-write|nonstrict-read-write|read-only" (1) />

(1)usage 说明了缓存的策略: transactional 、 read-write 、 nonstrict-read-write 或 read-only 。

另外(首选?),你可以在hibernate.cfg.xml中指定<class-cache>和<collection-cache>元素。

这里的usage 属性指明了缓存并 发策略(cache concurrency strategy)

只读 缓存(read only)

如果你的应用程序只需读取一个持久化类的实例,而无需对其修改, 那么就可以对其进行只读 缓存。这是最简单,也是实用性最好的方法。甚至在集群中,它也能完美地运作。

<class name="eg.Immutable" mutable="false"> <cache usage="read-only"/> .... </class>

读/写缓存( read/write)

如果应用程序需要更新数据,那么使用读/写缓存 比较合适。 如果应用程序要求“序列化事务”的隔离级别(serializable transaction isolation level),那么就决不能使用这种缓存策略。 如果在JTA环境中使用缓存,你必须指定hibernate.transaction.manager_lookup_class 属 性的值, 通过它,Hibernate才能知道该应用程序中JTA的TransactionManager 的 具体策略。 在其它环境中,你必须保证在Session.close() 、或Session.disconnect() 调用前, 整个事务已经结束。 如果你想在集群环境中使用此策略,你必须保证底层的缓存实现支持锁定(locking)。Hibernate内置的缓存策略并不支持锁定功能。

<class name="eg.Cat" .... > <cache usage="read-write"/> .... <set name="kittens" ... > <cache usage="read-write"/> .... </set> </class>

非严格读/写缓存(nonstrict read/write)

如果应用程序只偶尔需要更新数据(也就是说,两个事务同时更新同一记录的情况很不常见),也不需要十分严格的事务隔离, 那么比较适合使用非严格读/写缓存 策略。如果在JTA环境中使用该策略, 你必须为其指定hibernate.transaction.manager_lookup_class 属性的值, 在其它环境中,你必须保证在Session.close() 、或Session.disconnect() 调用前, 整个事务已经结束

-------------------------------------------------------------------------

在jBPM中使用不少这样的非严格读/写缓存的处理:

<?xmlversion="1.0"?>

<!DOCTYPEhibernate-mappingPUBLIC

"-//Hibernate/HibernateMappingDTD3.0//EN"

"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mappingdefault-access="field">

<classname="org.jbpm.context.def.VariableAccess"

table="JBPM_VARIABLEACCESS"

lazy="false">

<cacheusage="nonstrict-read-write"/>

<idname="id"column="ID_"><generatorclass="native"/></id>

<propertyname="variableName"column="VARIABLENAME_"/>

<propertyname="access"column="ACCESS_"/>

<propertyname="mappedName"column="MAPPEDNAME_"/>

</class>

</hibernate-mapping>

它的ehcache.xml是这样配置的:

<ehcache>

<defaultCache

maxElementsInMemory="100000"

eternal="true"

overflowToDisk="false"

diskPersistent="false"

/>

</ehcache>

Hibernate Annotation 中配置EhCache缓存

1.首先设置EhCache,建立配置文件ehcache.xml,默认的位置在class-path,可以放到你的src目录下:

  1. xml  version ="1.0"  encoding ="UTF-8" ?>   
  2. < ehcache >   
  3.  < diskStore  path ="java.io.tmpdir" />     
  4.   < defaultCache   
  5.    maxElementsInMemory ="10000"    
  6.    eternal ="false"    
  7.   
  8.    overflowToDisk ="true"    
  9.   
  10.    timeToIdleSeconds ="300"    
  11.    timeToLiveSeconds ="180"    
  12.    diskPersistent ="false"   
  13.    diskExpiryThreadIntervalSeconds = "120" />     
  14. ehcache >   

2.在Hibernate配置文件中设置:

       

此外,可以把cache.use_second_level_cache设置为false关闭所有的hibernate二级缓存。但此属性对指定<cache>的类缺省为true。   3.  为了使用二级缓存,需要在每一个Hibernate Entity上配置。

  1. @Entity   
  2. @Cache (usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)   
  3. public   class  Forest { ... }  
  4. @OneToMany (cascade=CascadeType.ALL, fetch=FetchType.EAGER)   
  5. @JoinColumn (name= "CUST_ID" )   
  6. @Cache (usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)   
  7. public  SortedSet getTickets() {   
  8.      return  tickets;   
  9. }  
  1. @Cache (   
  2.     CacheConcurrencyStrategy usage();          (1 )   
  3.     String region()  default   "" ;                       (2 )   
  4.     String include()  default   "all" ;                  (3 )   
  5. )  

(1)usage:提供缓存对象的事务隔离机制,可选值有以下几种

(NONE,READ_ONLY,NONSTRICT_READ_WRITE,READ_WRITE,TRANSACTIONAL)

(2)region(optional):指定缓存的区域,默认是类的全限定名。利用缓存区域,可以更精确的指定每个区域的缓存超前策略。如果指定了缓存区域前缀(在hibernate.cfg.xml中设置cache.region_prefix属性为一个字符串),则所有的缓存区域名前将加上这个前缀。

(3)include(optional):alltoincludeallproperties,non-lazytoonlyincludenonlazyproperties(defaultall).

如果不是使用annotation的话,则是在Hbm文件中添加cache usage="read-only"

---------------------------------------------

本次项目使用hibernate + jpa, 其配置如下:

jap的persistence.xml文件

<persistence xmlns="http://java.sun.com/xml/ns/persistence"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://java.sun.com/xml/ns/persistencehttp://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"

version="1.0">

<persistence-unitname="punit"transaction-type="RESOURCE_LOCAL">

<provider>org.hibernate.ejb.HibernatePersistence</provider>

<mapping-file>IptvFeeORM.xml</mapping-file>

<properties>

<propertyname="hibernate.jdbc.batch_size"value="100"/>

<propertyname="hibernate.cache.use_second_level_cache"

value="true"/>

<propertyname="hibernate.cache.provider_class"

value="net.sf.ehcache.hibernate.EhCacheProvider"/>

<propertyname="hibernate.cache.use_minimal_puts"value="true"/>

<propertyname="net.sf.ehcache.configurationResourceName"value="/hibernate_ehcache.xml"/>

</properties>

</persistence-unit>

</persistence>

cache.xml配置文件:

<?xml version="1.0" encoding="UTF-8"?>

<ehcache>

<diskStorepath="./ehcache/hibernate/diskStore"/>

<defaultCachemaxElementsInMemory="5000000"eternal="false"

timeToIdleSeconds="600"timeToLiveSeconds="600"overflowToDisk="false"

diskPersistent="false"diskExpiryThreadIntervalSeconds="1200"

memoryStoreEvictionPolicy="LRU">

</defaultCache>

</ehcache>

spring引用的数据库配置文件 IptvFeeConfig.properties :

#database config

jdbc.driver=oracle.jdbc.driver.OracleDriver

jdbc.url=jdbc:oracle:thin:@192.168.1.1:1521:love

jdbc.username=you

jdbc.password=me

jdbc.maxActive=5

jdbc.maxIdle=5

jpa.database=ORACLE

jpa.showSql=true

jpa.generateDdl=false

jdbc.getdate.sql=select sysdate from dual

spring 里面的配置文件:

<bean id="propertyConfigurer"

class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">

<propertyname="location"value="classpath:IptvFeeConfig.properties"/>

    </bean>

<bean

        class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />

<beanid="entityManagerFactory"

class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">

<propertyname="dataSource"ref="dataSource"/>

<propertyname="persistenceXmlLocation"value="classpath:IptvFeePersistence.xml"/>

<propertyname="jpaVendorAdapter">

<beanclass="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">

<propertyname="database"value="${jpa.database}"/>

<propertyname="showSql"value="${jpa.showSql}"/>

<propertyname="generateDdl"value="${jpa.generateDdl}"></property>

<propertyname="databasePlatform"value="org.hibernate.dialect.OracleDialect"/>

</bean>

</property>

    </bean>

<beanid="dataSource"class="org.apache.commons.dbcp.BasicDataSource"destroy-method="close">

<propertyname="driverClassName">

<value>${jdbc.driver}</value>

</property>

<propertyname="url">

<value>${jdbc.url}</value>

</property>

<propertyname="username">

<value>${jdbc.username}</value>

</property>

<propertyname="password">

<value>${jdbc.password}</value>

</property>

<propertyname="maxActive">

<value>${jdbc.maxActive}</value>

</property>

<propertyname="maxIdle">

<value>${jdbc.maxIdle}</value>

</property>

<propertyname="testOnBorrow"value="true"/>

<propertyname="validationQuery"value="${jdbc.getdate.sql}"/>

    </bean>

<beanid="transactionManager"class="org.springframework.orm.jpa.JpaTransactionManager">

<propertyname="entityManagerFactory"ref="entityManagerFactory"/>

    </bean>

<tx:annotation-driventransaction-manager="transactionManager"

        proxy-target-class="true" />

<beanid="org.springframework.jdbc.core.JdbcTemplate"class="org.springframework.jdbc.core.JdbcTemplate">

<propertyname="dataSource"ref="dataSource"></property>

    </bean>

<beanid="com.domain.repository.Repository"

class="com.repository.RepositoryJpaImpl">

<propertyname="jdbcTemplate"ref="org.springframework.jdbc.core.JdbcTemplate"/>

    </bean>

实体class

@Cache(usage=CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)public class BillContent extends AbstractPersistable implements Persistable

转自:http://blog.csdn.net/cuker919/article/details/5966862

相关推荐