`

Hibernate Cache

阅读更多

Cache In Hibernate
HIBERNATE中的CACHE有两级. 一级是在Session范围内的CACHE. 即每个Session有自己的一个CACHE, 当前操作的对象都会被保留在CACHE中. 但是Session关闭后这个CACHE也就没有. 可见这级CACHE的生命期是很短的. 另一级CACHE是在SessionFactory范围的, 可以被来自同一个SessionFactory的Session共享. 在HIBERNATE的文档中称其为SECOND LEVEL CACHE. 显然后者的优势较明显, 也比较复合当前的使用环境.

还有一个类型的CACHE就是QueryCache. 它的作用就是缓存一个Query以及Query返回对象的Identifier以及对象的类型. 有了QueryCache后就可以高效的使用SECOND LEVEL CACHE.

Second Level Cache
这里使用ehcache来作为HIBERNATE的SECOND LEVEL CACHE. 由于这是HIBERNATE默认的CACHE提供者, 所以无须做什么设置. 两个很简单的POJO, Person & Address, 一对多的关系. HBM如下:
[code:1]
<hibernate-mapping
package="goncha.hb.bean">
<class name="Person" table="hb.person">
<!-- enable second level cache -->
<cache usage="read-write"/>

<id name="id">
<generator class="native"/>
</id>

<property name="name" not-null="true" unique="true"/>
<property name="age" type="java.lang.Integer" not-null="true"/>

<!-- relationship -->
<set name="addresses" lazy="true" inverse="true" cascade="save-update">
<key column="owner_id"/>
<one-to-many class="Address"/>
</set>
</class>
</hibernate-mapping>


<hibernate-mapping
package="goncha.hb.bean">
<class name="Address" table="hb.address">
<!-- enable second level cache -->
<cache usage="read-write"/>

<id name="id">
<generator class="native"/>
</id>

<property name="location" not-null="true" unique="true"/>
<property name="phone" not-null="true" unique="true"/>

<many-to-one name="owner" column="owner_id" not-null="true"/>
</class>
</hibernate-mapping>
[/code:1]
这两个类都使用了SECOND LEVEL CACHE, 并且两者之间存在关系映射.

ehcache的配置文件ehcache.xml:
[code:1]
<ehcache>

<diskStore path="java.io.tmpdir"/>

 

<defaultCache

maxElementsInMemory="10000"

eternal="false"

timeToIdleSeconds="120"

timeToLiveSeconds="120"

overflowToDisk="true"

/>

 

<cache name="goncha.hb.bean.Person"

maxElementsInMemory="10"

eternal="false"

timeToIdleSeconds="100"

timeToLiveSeconds="100"

overflowToDisk="false"

/>

 

<cache name="goncha.hb.bean.Address"

maxElementsInMemory="10"

eternal="false"

timeToIdleSeconds="100"

timeToLiveSeconds="100"

overflowToDisk="false"

/>

 

</ehcache>
[/code:1]

一段简单的测试代码, 可以清楚的看到HIBERNATE如何来使用SECOND LEVEL CACHE. 在运行这段代码前需要作一些工作: 在HIBERNATE的配置文件中允许输出生成的SQL语句; 在LOG4J的配置文件中, 处了net.sf.hibernate.cache在DEBUG级别, 其余都在WARN级别, 为了没有干扰 :)
[code:1]
# log4j.properties
log4j.logger.net.sf.hibernate=warn
log4j.logger.net.sf.hibernate.cache=debug


# hibernate.properties
hibernate.show_sql true
[/code:1]

至此就可以运行以下代码
[code:1]
//: Main.java

package goncha.hb;

import java.util.Iterator;
import java.util.List;
import java.util.Set;

import net.sf.hibernate.Query;
import net.sf.hibernate.Session;
import net.sf.hibernate.SessionFactory;
import net.sf.hibernate.Transaction;
import net.sf.hibernate.cfg.Configuration;

import goncha.hb.bean.*;


public class Main {

public static void main(String[] args) throws Exception {
SessionFactory sessions = buildSessionFactory();

pushDataIntoCache(sessions);
popDataFromCache(sessions);
}

static SessionFactory buildSessionFactory() throws Exception {
Configuration config = new Configuration();
config.addClass(Person.class).addClass(Address.class);
return config.buildSessionFactory();
}

static void pushDataIntoCache(SessionFactory sessions) throws Exception {
System.out.println("======= Push some data into cache =======");

Session sess = sessions.openSession();
Transaction tx = sess.beginTransaction();

Person goncha = (Person)sess.load(Person.class, new Integer(1));
System.out.println(goncha);

Person chengang = (Person)sess.load(Person.class, new Integer(2));
System.out.println(chengang);

goncha.getAddresses().size();
tx.commit();
sess.close();
}

static void popDataFromCache(SessionFactory sessions) throws Exception {
System.out.println("======= Pop some data into cache =======");

Session sess = sessions.openSession();
Transaction tx = sess.beginTransaction();

Person goncha = (Person)sess.load(Person.class, new Integer(1));
System.out.println(goncha);

Person chengang = (Person)sess.load(Person.class, new Integer(2));
System.out.println(chengang);

Person tommy = (Person)sess.load(Person.class, new Integer(3));
System.out.println(tommy);

Person mary = (Person)sess.load(Person.class, new Integer(4));
System.out.println(mary);


List persons = sess.find("from Person as person");

Set addresses = goncha.getAddresses();
Iterator it = addresses.iterator();
while(it.hasNext()) {
System.out.println((Address)it.next());
}

tx.commit();
sess.close();
}
}
[/code:1]

以下是程序的输出
[code:1]
Buildfile: build.xml

init:

build:

run:
[java] 23:14:04,878 DEBUG CacheFactory:32 - cache for: goncha.hb.bean.Person usage strategy: read-write
[java] 23:14:05,156 DEBUG CacheFactory:32 - cache for: goncha.hb.bean.Address usage strategy: read-write
[java] Initializing c3p0 pool... com.mchange.v2.c3p0.PoolBackedDataSource@17bd6a1 [ connectionPoolDataSource -> com.mchange.v2.c3p0.WrapperConnectionPoolDataSource@8b819f [ acquireIncrement -> 2, autoCommitOnClose -> false, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, idleConnectionTestPeriod -> 3000, initialPoolSize -> 2, maxIdleTime -> 5000, maxPoolSize -> 2, maxStatements -> 100, minPoolSize -> 2, nestedDataSource -> com.mchange.v2.c3p0.DriverManagerDataSource@147ee05 [ description -> null, driverClass -> null, factoryClassLocation -> null, jdbcUrl -> jdbc:postgresql:test, properties -> {user=pgsql, password=pgsql} ] , propertyCycle -> 300, testConnectionOnCheckout -> false ] , factoryClassLocation -> null, numHelperThreads -> 3 ]
[java] 23:14:07,390 INFO UpdateTimestampsCache:35 - starting update timestamps cache at region: net.sf.hibernate.cache.UpdateTimestampsCache
[java] 23:14:07,396 INFO QueryCache:39 - starting query cache at region: net.sf.hibernate.cache.QueryCache
[java] __======= Push some data into cache =======__
[java] 23:14:07,492 DEBUG ReadWriteCache:68 - Cache lookup: 1
[java] 23:14:07,494 DEBUG ReadWriteCache:84 - Cache miss: 1
[java] Hibernate: select person0_.id as id0_, person0_.name as name0_, person0_.age as age0_ from hb.person person0_ where person0_.id=?
[java] 23:14:07,584 DEBUG ReadWriteCache:132 - Caching: 1
[java] 23:14:07,594 DEBUG ReadWriteCache:143 - Cached: 1
[java] Person ['goncha'; 23]
[java] 23:14:07,599 DEBUG ReadWriteCache:68 - Cache lookup: 2
[java] 23:14:07,601 DEBUG ReadWriteCache:84 - Cache miss: 2
[java] Hibernate: select person0_.id as id0_, person0_.name as name0_, person0_.age as age0_ from hb.person person0_ where person0_.id=?
[java] 23:14:07,609 DEBUG ReadWriteCache:132 - Caching: 2
[java] 23:14:07,611 DEBUG ReadWriteCache:143 - Cached: 2
[java] Person ['chengang'; 23]
[java] Hibernate: select addresses0_.id as id__, addresses0_.owner_id as owner_id__, addresses0_.id as id0_, addresses0_.location as location0_, addresses0_.phone as phone0_, addresses0_.owner_id as owner_id0_ from hb.address addresses0_ where addresses0_.owner_id=?
[java] 23:14:07,624 DEBUG ReadWriteCache:132 - Caching: 1
[java] 23:14:07,630 DEBUG ReadWriteCache:143 - Cached: 1
[java] 23:14:07,632 DEBUG ReadWriteCache:132 - Caching: 2
[java] 23:14:07,633 DEBUG ReadWriteCache:143 - Cached: 2
[java] 23:14:07,635 DEBUG ReadWriteCache:132 - Caching: 6
[java] 23:14:07,637 DEBUG ReadWriteCache:143 - Cached: 6
[java] __======= Pop some data into cache =======__
[java] 23:14:07,669 DEBUG ReadWriteCache:68 - Cache lookup: 1
[java] 23:14:07,671 DEBUG ReadWriteCache:78 - Cache hit: 1
[java] Person ['goncha'; 23]
[java] 23:14:07,675 DEBUG ReadWriteCache:68 - Cache lookup: 2
[java] 23:14:07,678 DEBUG ReadWriteCache:78 - Cache hit: 2
[java] Person ['chengang'; 23]
[java] 23:14:07,680 DEBUG ReadWriteCache:68 - Cache lookup: 3
[java] 23:14:07,682 DEBUG ReadWriteCache:84 - Cache miss: 3
[java] Hibernate: select person0_.id as id0_, person0_.name as name0_, person0_.age as age0_ from hb.person person0_ where person0_.id=?
[java] 23:14:07,691 DEBUG ReadWriteCache:132 - Caching: 3
[java] 23:14:07,693 DEBUG ReadWriteCache:143 - Cached: 3
[java] Person ['tommy'; 21]
[java] 23:14:07,698 DEBUG ReadWriteCache:68 - Cache lookup: 4
[java] 23:14:07,699 DEBUG ReadWriteCache:84 - Cache miss: 4
[java] Hibernate: select person0_.id as id0_, person0_.name as name0_, person0_.age as age0_ from hb.person person0_ where person0_.id=?
[java] 23:14:07,704 DEBUG ReadWriteCache:132 - Caching: 4
[java] 23:14:07,706 DEBUG ReadWriteCache:143 - Cached: 4
[java] Person ['mary'; 18]
[java] Hibernate: select person0_.id as id, person0_.name as name, person0_.age as age from hb.person person0_
[java] 23:14:07,768 DEBUG ReadWriteCache:132 - Caching: 5
[java] 23:14:07,770 DEBUG ReadWriteCache:143 - Cached: 5
[java] 23:14:07,772 DEBUG ReadWriteCache:132 - Caching: 6
[java] 23:14:07,774 DEBUG ReadWriteCache:143 - Cached: 6
[java] Hibernate: select addresses0_.id as id__, addresses0_.owner_id as owner_id__, addresses0_.id as id0_, addresses0_.location as location0_, addresses0_.phone as phone0_, addresses0_.owner_id as owner_id0_ from hb.address addresses0_ where addresses0_.owner_id=?
[java] 23:14:07,809 DEBUG ReadWriteCache:132 - Caching: 1
[java] 23:14:07,811 DEBUG ReadWriteCache:152 - Item was already cached: 1
[java] 23:14:07,816 DEBUG ReadWriteCache:132 - Caching: 2
[java] 23:14:07,817 DEBUG ReadWriteCache:152 - Item was already cached: 2
[java] 23:14:07,819 DEBUG ReadWriteCache:132 - Caching: 6
[java] 23:14:07,820 DEBUG ReadWriteCache:152 - Item was already cached: 6
[java] Address ['goncha'; 'newyork']
[java] Address ['goncha'; 'shanghai']
[java] Address ['goncha'; 'guangzhou']

 

BUILD SUCCESSFUL
Total time: 7 seconds
[/code:1]

这个结果很出乎意外, HERBNATE只能在Session.load()方法中使用CACHE. pushDataIntoCache()方法成功地给CACHE注入两个Person对象("goncha", "chengang")以及三个Address对象(与"goncha"关联). 再看看popDataFromCache()方法. 使用Session.load()时, "goncha"与"chengang"对应的Person对象都是从CACHE中获得, 其余两个是CACHE MISS的, 正常举动. 而Session.find()的数据获取与CACHE没有关系, 完全由JDBC来操办. 最后只是把从JDBC获得的对象注入CACHE. 通过关系查找对象的过程和Session.find()没有异样, 甚至CACHE还报出对象已存在的消息.

不知这样的测试是否会偏面. 但是在具体的使用环境中就是Session.find()和Relationship Collection占了多数. 像上面的例子那样, CACHE不仅没有用到还白白占了内存. 所以在HIBERNATE中使用CACHE还是需要根据具体情况来定制.

Query Cache
老实说, 要做到在JDBC查询之前决定哪些数据需要从JDBC来还是CACHE来不是件容易事. 但是HIBERNATE还是很好地完成了这个任务. 前面说过QueryCache用来缓存查询语句, 及查询结果集中对象的Identifier与Type. 当再次使用已缓存的Query时, 就可以通过对象的Identifier与Type在SECOND LEVEL CACHE中查找实际的对象.

使用QueryCache时需要在hibernate配置文件中设置如下属性:
[code:1]
hibernate.cache.use_query_cache true
[/code:1]

在程序中需要为Query对象设置Cachable属性:
[code:1]
Query query = sess.createQuery("from AccountingPeriod as period "
+ "where period.id.dealerId = ? order by period.id.orderType asc, "
+ "period.id.accountingPeriod asc");
query.setCacheable(true);
query.setInteger(0, dealerId.intValue());
List rs = query.list();
[/code:1]

 

分享到:
评论

相关推荐

    hibernate cache

    - **配置**:通过 `hibernate.cache.use_second_level_cache` 配置启用,然后选择合适的提供者。 - **分区**:缓存数据可以按类或特定查询进行分区,以便更高效地管理。 - **过期策略**:可通过设置缓存的生存时间或...

    spring hibernate cache

    2. 绑定 Hibernate 二级缓存:Spring Cache 可以与 Hibernate 二级缓存集成,通过配置让 Spring 的缓存操作直接作用于 Hibernate 的二级缓存。 3. 缓存策略:根据业务需求,调整缓存的过期时间、更新策略等,确保...

    hibernate_cache_level_1

    本篇文章将深入探讨“hibernate_cache_level_1”这一主题,即Hibernate的二级缓存,以及在项目中的应用。 一级缓存是Hibernate内置的Session级别的缓存,它是事务性的,每个Session都有自己的缓存,当Session关闭时...

    Hibernate 使用缓存时,数据同步问题

    3. **设置缓存模式**:在查询时,可以设置`CacheMode.REFRESH`,强制Hibernate在执行查询前刷新查询缓存区域,从而获取最新的数据。这是一种更高效的替代`SessionFactory.evictQueries()`的方法,专门用于处理底层...

    hibernate4.0使用二级缓存jar包

    &lt;property name="hibernate.cache.region.factory_class"&gt;org.hibernate.cache.ehcache.EhCacheRegionFactory 3.3配置如下: &lt;property name="hibernate.cache.use_second_level_cache"&gt;true &lt;property name="cache...

    java.lang.NoClassDefFoundError: Lorg/hibernate/cache/CacheProvider

    在这个特定的情况下,错误信息 "NoClassDefFoundError: Lorg/hibernate/cache/CacheProvider" 指示的是 `org.hibernate.cache.CacheProvider` 类无法被找到。 `org.hibernate.cache.CacheProvider` 是Hibernate框架...

    WebWork.Spring.Hibernate整合开发网络书城全系列视屏6

    4. 性能优化:讨论如何通过缓存机制(如Spring的HibernateCache)和数据库连接池来提高系统的性能。 5. 安全性:简述如何集成Spring Security,为网络书城应用添加用户认证和授权功能。 总的来说,这个课程会带领...

    Hibernate 缓存 实例

    其中,`hibernate.cache.provider_class`指定了使用Ehcache作为缓存提供者,`hibernate.cache.provider_configuration_file_resource_path`指定了Ehcache的配置文件路径,`hibernate.show_sql`则控制是否显示SQL日志...

    hibernate一级和二级缓存配置与详解

    &lt;property name="hibernate.cache.region.factory_class"&gt;org.hibernate.cache.ehcache.EhCacheRegionFactory &lt;property name="hibernate.cache.use_second_level_cache"&gt;true ``` 接下来,为特定的实体类或者查询...

    Hibernate的cache缓存解析

    ### Hibernate的Cache缓存解析 #### 基本的缓存原理 在深入探讨Hibernate缓存之前,我们先来了解一下缓存的基本原理。缓存是一种用于提高数据访问速度的技术,通常用于存储最近或频繁访问的数据副本。通过将这些...

    启动tomcat报错org.hibernate.cache.CacheProvider

    标题中的“启动tomcat报错org.hibernate.cache.CacheProvider”指的是在尝试启动Apache Tomcat服务器时遇到了与Hibernate缓存提供者相关的错误。这通常涉及到Hibernate框架的配置或运行时环境问题。Hibernate是一个...

    hibernate_cache_level_2.rar_java_staredb4u

    本压缩包“hibernate_cache_level_2.rar”聚焦于Hibernate框架中的第二级缓存,这是一个关键特性,用于提高应用程序的性能。在这个主题下,我们将深入探讨Hibernate的二级缓存机制、其工作原理以及如何在项目中有效...

    最新二级缓存memcached,支持hibernate4

    解决目前memcached不支持hibernate4的缺陷,hibernate配置&lt;property name="hibernate.cache.region.factory_class"&gt;com.googlecode.hibernate.memcached.MemcachedRegionFactory&lt;/property&gt;

    springboot+jpa(hibernate配置redis为二级缓存) springboot2.1.4

    spring.jpa.hibernate.cache.region.factory_class=org.hibernate.cache.redis.hibernate5.SingletonRedisRegionFactory ``` 4. **实体类注解**: 对于需要缓存的实体类,可以使用`@Cacheable`、`@CacheEvict`等...

    hibernate二级缓存(包括注解方式)

    &lt;property name="hibernate.cache.region.factory_class"&gt;org.hibernate.cache.ehcache.EhCacheRegionFactory &lt;property name="net.sf.ehcache.configurationResourceName"&gt;ehcache.xml ``` 接着,在`ehcache.xml`...

    hibernate_cache_level_1.rar_alreadydcc_java

    本文将深入探讨Hibernate中的缓存机制,特别是第一级缓存,并结合"hibernate_cache_level_1.rar"这个压缩包文件,解析其在实际应用中的实现。 一、Hibernate缓存概述 Hibernate提供了两种级别的缓存:一级缓存和二...

    Hibernate参数设置一览表

    默认使用的是`org.hibernate.cache.internal.NoCachingRegionFactory`,若需开启二级缓存,可设置为`org.hibernate.cache.ehcache.EhCacheRegionFactory`。 9. **hibernate.cache.use_query_cache** 是否启用查询...

    struts2+spring4+hibernate3 Helloworld

    版本差异太难搞了,找半天才找到错误,主要是包冲突 NoSuchMethodError: org.jboss....NoClassDefFoundError: org/hibernate/cache/spi/RegionFactory org.hibernate.cache.spi.RegionFactory 记录下来,以备不时

Global site tag (gtag.js) - Google Analytics