`

JPA二级缓存通过Ehcache的实现

 
阅读更多
一级缓存是Session级别的缓存,在Session关闭时,一级缓存就会失效。

第二级缓存是一个可插拔的的缓存插件,它是由SessionFactory负责管理。由于SessionFactory对象的生命周期和应用程序的整个过程对应,因此第二级缓存是进程范围或者集群范围的缓存。这个缓存中存放的对象的松散数据。第二级对象有可能出现并发问题,因此需要采用适当的并发访问策略,该策略为被缓存的数据提供了事务隔离级别。缓存适配器用于把具体的缓存实现软件与Hibernate集成。第二级缓存是可选的,可以在每个类或每个集合的粒度上配置第二级缓存,如EhCache 、JBossCache、OsCache等。


二级缓存应用场景如下:

1)很少被修改的数据

2)不是很重要的数据,允许出现偶尔并发的数据

3)不会被并发访问的数据

4)参考数据

配置Ehcache:

1. persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" 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/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
    <persistence-unit name="project" transaction-type="RESOURCE_LOCAL">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <properties>
             <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver" />
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect" />
            <property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/project?autoReconnect=true&amp;useUnicode=true&amp;characterEncoding=UTF-8" />
            <property name="hibernate.connection.username" value="root" />
            <property name="hibernate.connection.password" value="password" />
            <property name="hibernate.c3p0.max_size" value="200" />
            <property name="hibernate.c3p0.min_size" value="2" />
            <property name="hibernate.c3p0.max_statements" value="100" />
            <property name="hibernate.c3p0.acquire_increment" value="1" />
            <property name="hibernate.c3p0.validate" value="true" />
            <property name="hibernate.c3p0.testConnectionOnCheckout" value="true" />  
             <property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.EhCacheRegionFactory" />
            <property name="hibernate.cache.provider_configuration" value="/ehcache.xml" />           
            <property name="hibernate.generate_statistics" value="true" /> 
            <property name="hibernate.cache.use_second_level_cache" value="true" />
            <property name="hibernate.cache.use_query_cache" value="true" />
            <property name="hibernate.show_sql" value="true" />
        </properties>
    </persistence-unit>
</persistence>

2. ehcache.xml和properties文件一起放在resource目录下(src/main/resources)

<!-- 
        name:cache唯一标识  
        eternal:缓存是否永久有效  
        maxElementsInMemory:内存中最大缓存对象数 
        overflowToDisk(true,false):缓存对象达到最大数后,将缓存写到硬盘中 
        diskPersistent:硬盘持久化 
        timeToIdleSeconds:缓存清除时间  
        timeToLiveSeconds:缓存存活时间 
        memoryStoreEvictionPolicy:缓存清空策略 
        1.FIFO:first in first out 先讲先出 
        2.LFU: Less Frequently Used 一直以来最少被使用的 
        3.LRU:Least Recently Used  最近最少使用的 
--> 
<?xml version="1.0" encoding="UTF-8" ?>
<ehcache xmlns:xsi="w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="ehcache.xsd" updateCheck="false" monitoring="autodetect" dynamicConfig="true">
    <diskStore path="C:/Temp/ehcache/"/>
   
    <defaultCache maxElementsInMemory="100" eternal="false"
           timeToIdleSeconds="1200" timeToLiveSeconds="1200" overflowToDisk="true" clearOnFlush="true">
    </defaultCache>
   
    <cache name="org.test.persistent.entity.Scenario"
           maxElementsInMemory="100"
           eternal="false"
           timeToIdleSeconds="1800"
           timeToLiveSeconds="3600"
           overflowToDisk="true">
    </cache>
    <cache name="org.test.persistent.entity.ProjectTree"
           maxElementsInMemory="100"
           eternal="false"
           timeToIdleSeconds="1800"
           timeToLiveSeconds="3600"
           overflowToDisk="true">
    </cache>
    <cache name="org.hibernate.cache.spi.UpdateTimestampsCache"
        maxElementsInMemory="100"
        timeToIdleSeconds="1800"
        timeToLiveSeconds="3600"
        eternal="false"
        overflowToDisk="true">
    </cache>
</ehcache>

3. 实体类:

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.SequenceGenerator;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import javax.persistence.Cacheable;

@Entity
@Table(name = "scenario", schema = "projecttable")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE, region="org.test.persistent.entity.Scenario")
public class Scenario implements Serializable
{
。。。。
}


4. 数据查询

public List<Scenario> searchScenariobyParent(Integer parentId)
    {
        EntityManager em = ProjectDBFactory.getInstance().getEntityManager();
        try {
            TypedQuery<Scenario> query = em.createQuery(
                    "from Scenario as s where s.obsolete!=1 and s.parentId=? order by s.name, s.scenarioStatusId",
                    Scenario.class);
            query.setParameter(1, parentId);
            query.setHint("org.hibernate.cacheable", true);
            if (query instanceof org.hibernate.ejb.QueryImpl) {
                ((org.hibernate.ejb.QueryImpl)query).getHibernateQuery().setCacheable(true);
            }
            List<Scenario> scenarios = query.getResultList();     
           
            EntityManagerImpl empImpl = (EntityManagerImpl)em;
            System.out.println(empImpl.getSession().getStatistics());
                   System.out.println(empImpl.getSession().getSessionFactory().getStatistics());

            return scenarios;
        } finally {
            em.close();
        }
    }

5. pom.xml

<!-- jpa begin -->
<properties>
        <endorsed.dir>${project.build.directory}/endorsed</endorsed.dir>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <javawebapi.version>7.0</javawebapi.version>
        <hibernate.version>4.2.3.Final</hibernate.version>
        <mysql-connector-java.version>5.1.25</mysql-connector-java.version>
        <junit.version>4.11</junit.version>
        <log4j.version>1.2.16</log4j.version>
        <slf4j.version>1.4.3</slf4j.version>
        <project.build.sourceEncoding>utf-8</project.build.sourceEncoding>
        <parameters.section>development</parameters.section>
        <timestamp>${maven.build.timestamp}</timestamp>
        <maven.build.timestamp.format>dd MMMM yyyy HH:mm z</maven.build.timestamp.format>
     </properties>
<dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>${hibernate.version}</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>${hibernate.version}</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-c3p0</artifactId>
            <version>${hibernate.version}</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-ehcache</artifactId>
            <version>${hibernate.version}</version>
        </dependency>
        <dependency>
            <groupId>net.sf.ehcache</groupId>
            <artifactId>ehcache</artifactId>
            <version>2.10.1</version>
            <type>pom</type>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>${mysql-connector-java.version}</version>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <version>1.3.162</version>
        </dependency>
        <dependency>
            <groupId>javax.transaction</groupId>
            <artifactId>jta</artifactId>
            <version>1.1</version>
        </dependency>
        <dependency>
            <groupId>com.mchange</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.5.1</version>
        </dependency>
        <!-- jpa end -->
        <!-- Logging begin -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>${log4j.version}</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.7</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.7</version>
        </dependency>
        <!-- Logging end -->

6. 缓存方式:

缓存 CacheConcurrencyStrategy 方式有五种缓存方式:
1) CacheConcurrencyStrategy.NONE,不适用,默认
2) CacheConcurrencyStrategy.READ_ONLY ,只读模式,在此模式下,如果对数据进行更新操作,会有异常;
3) CacheConcurrencyStrategy.READ_WRITE ,读写模式在更新缓存的时候会把缓存里面的数据换成一个锁,其它事务如果去取相应的缓存数据,发现被锁了,直接就去数据库查询;
4) CacheConcurrencyStrategy.NONSTRICT_READ_WRITE ,不严格的读写模式则不会的缓存数据加锁;
5) CacheConcurrencyStrategy.TRANSACTIONAL ,事务模式指缓存支持事务,当事务回滚时,缓存也能回滚,只支持 JTA 环境。


参考:
http://blog.csdn.net/zwan0518/article/details/8672245
http://www.360doc.com/content/13/0411/15/2569758_277586886.shtml
http://tuhaitao.iteye.com/blog/568653
http://blog.csdn.net/tjcyjd/article/details/10922577
http://www.yoodb.com/article/display/1071
http://www.oschina.net/question/54100_31552?fromerr=F8GYw9oa
http://acupof.blogspot.jp/2008/01/background-hibernate-comes-with-three.html#!/2008/01/background-hibernate-comes-with-three.html
http://cxl2012.iteye.com/blog/1944489
http://wenku.baidu.com/view/86fb9f2f0066f5335a812126.html
http://www.xlgps.com/article/401738.html
http://www.ehcache.org/generated/2.9.0/pdf/Integrations.pdf  Ehcache集成各种环境
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics