大家都了解对于信息的展示应用中解决对数据库的频繁访问主要有两种手段。
其一是生成静态文件进行存储,其二是采用数据换成技术。
hibernate + ehcache 就是采用第二种方式,也就是对数据的首次访问时取得读取数据,并应用缓存配置的吧取得的数据进行缓存,
以备下次读取时直接从缓存数据中读取,无需再次访问数据库。
hibernate 3.2
echache 1.2.3
eclipse 3.3
EhCache是一个纯Java程序,可以在Hibernate中作为一个插件引入。它具有运行速度快、结构简单、占用内存小、很小的依赖性、支持多CPU服务器、文档齐全等特点。
至于hibernate的使用这里不做介绍
用于EhCache是以插件形式加载的所以只需在hibernate.cfg.xml配置插入相关配置即可
其中
是对EhCache以及hibernate使用缓存的配置。
接下来在src根目录中创建缓存策略文件
创建一个用于测试的数据表
接下来我们需要对实体映射文件中加入缓存配置
以Test对象为例(相关dao 忽略)
<cache
usage="transactional|read-write|nonstrict-read-write|read-only"/>
ehcache 暂不支持transactional。
read-only:无需修改, 那么就可以对其进行只读缓存,注意,在此策略下,如果直接修改数据库,即使能够看到前台显示效果,但是将对象修改至cache中会报error,cache不会发生作用。另:删除记录会报错,因为不能在read-only模式的对象从cache中删除。
read-write:需要更新数据,那么使用读/写缓存 比较合适,前提:数据库不可以为serializable transaction isolation level(序列化事务隔离级别)
nonstrict-read-write:只偶尔需要更新数据(也就是说,两个事务同时更新同一记录的情况很不常见),也不需要十分严格的事务隔离,那么比较适合使用非严格读/写缓存策略。
下面我们进行测试
看一看控制台的输出
我们可以看到第二次查询的时候并没有从数据库中查询。
Java开发Q群:46176507
其一是生成静态文件进行存储,其二是采用数据换成技术。
hibernate + ehcache 就是采用第二种方式,也就是对数据的首次访问时取得读取数据,并应用缓存配置的吧取得的数据进行缓存,
以备下次读取时直接从缓存数据中读取,无需再次访问数据库。
hibernate 3.2
echache 1.2.3
eclipse 3.3
EhCache是一个纯Java程序,可以在Hibernate中作为一个插件引入。它具有运行速度快、结构简单、占用内存小、很小的依赖性、支持多CPU服务器、文档齐全等特点。
至于hibernate的使用这里不做介绍
用于EhCache是以插件形式加载的所以只需在hibernate.cfg.xml配置插入相关配置即可
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<!-- Generated by MyEclipse Hibernate Tools. -->
<hibernate-configuration>
<session-factory>
<property name="cache.provider_class">
org.hibernate.cache.EhCacheProvider
</property>
<property name="hibernate.cache.use_query_cache">true</property>
<property name="connection.driver_class">
com.mysql.jdbc.Driver
</property>
<!-- 指定连接数据库的url,hibernate连接的数据库名 -->
<property name="connection.url">
jdbc:mysql://localhost/test
</property>
<!-- 数据库用户名 -->
<property name="connection.username">root</property>
<!-- 数据库密码 -->
<property name="connection.password">root</property>
<!--用c3p0连接池连接所允许的最大连接数-->
<property name="hibernate.c3p0.max_size">20</property>
<!-- c3p0所允许的最少连接数 -->
<property name="hibernate.c3p0.min_size">1</property>
<!-- 指定连接池连接失效的时间 -->
<property name="hibernate.c3p0.timeout">50</property>
<!-- 指定连接池缓存最大的存储多少个statement -->
<property name="hibernate.c3p0.max_statements">100</property>
<!-- hibernate.c3p0.timeout表示连接对象多长时间应该被销毁,
注意,是”应该“,但是谁来销毁它呢,需要一个线程按照hibernate.c3p0.idle_test_period
设定的时间间隔去自动校验这些链接对象并销毁timeout的 -->
<property name="hibernate.c3p0.idle_test_period">30</property>
<!-- 当连接池里面的连接用完的时候,C3P0一下获取的新的连接数 -->
<property name="hibernate.c3p0.acquire_increment">2</property>
<!-- 连接数据库的数据库方言 org.hibernate.dialect.MySQLDialect-->
<property name="dialect">
org.hibernate.dialect.MySQLDialect
</property>
<!-- 每次都验证连接是否可用 -->
<property name="hibernate.c3p0.validate">true</property>
<property name="show_sql">true</property>
<mapping resource="test/hibernate/Test.hbm.xml" />
</session-factory>
</hibernate-configuration>
其中
<property name="cache.provider_class">
org.hibernate.cache.EhCacheProvider
</property>
<property name="hibernate.cache.use_query_cache">true</property>
是对EhCache以及hibernate使用缓存的配置。
接下来在src根目录中创建缓存策略文件
<?xml version="1.0" encoding="UTF-8"?>
<ehcache>
<diskStore path="ehcache"/> //缓存目录
<defaultCache
maxElementsInMemory="100000" //缓存中允许创建的最大对象数
eternal="false" //缓存中对象是否为永久的
overflowToDisk="true" //是否启用磁盘缓存
timeToIdleSeconds="1500" //对象在它过期前的空闲时间
timeToLiveSeconds="1500" //对象在它过期前的生存时间
/>
</ehcache>
创建一个用于测试的数据表
CREATE TABLE `test` (
`name1` varchar(255) NOT NULL,
`name2` varchar(255) default NULL,
`datetime` datetime default NULL,
PRIMARY KEY (`name1`)
)
接下来我们需要对实体映射文件中加入缓存配置
以Test对象为例(相关dao 忽略)
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!--
Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
<class name="test.hibernate.Test" table="test" catalog="admintools">
<cache usage="read-write"/>
<id name="name1" type="string">
<column name="name1" />
<generator class="assigned" />
</id>
<property name="name2" type="string">
<column name="name2" />
</property>
<property name="datetime" type="timestamp">
<column name="datetime" length="0" />
</property>
</class>
</hibernate-mapping>
<cache
usage="transactional|read-write|nonstrict-read-write|read-only"/>
ehcache 暂不支持transactional。
read-only:无需修改, 那么就可以对其进行只读缓存,注意,在此策略下,如果直接修改数据库,即使能够看到前台显示效果,但是将对象修改至cache中会报error,cache不会发生作用。另:删除记录会报错,因为不能在read-only模式的对象从cache中删除。
read-write:需要更新数据,那么使用读/写缓存 比较合适,前提:数据库不可以为serializable transaction isolation level(序列化事务隔离级别)
nonstrict-read-write:只偶尔需要更新数据(也就是说,两个事务同时更新同一记录的情况很不常见),也不需要十分严格的事务隔离,那么比较适合使用非严格读/写缓存策略。
下面我们进行测试
Test test = new Test();
test.setName1("name1_2");
test.setName2("name2_2");
Session session = HibernateSessionFactory.getSession();
Transaction tr = session.beginTransaction();
try{
session.saveOrUpdate(test);
tr.commit();
}catch(HibernateException e){
System.out.println(e.getMessages());
tr.rollback();
}finally{
session.close();
}
System.out.println("-----------");
session = HibernateSessionFactory.getSession();
tr = session.beginTransaction();
try{
Test tt = (Test) session.get("test.hibernate.Test", "name1_2");
System.out.println(tt.getName1()+" "+tt.getName2());
}catch(HibernateException e){
e.printStackTrace();
System.out.println(e.getMessages());
tr.rollback();
}finally{
session.close();
}
System.out.println("-----");
session = HibernateSessionFactory.getSession();
tr = session.beginTransaction();
try{
Test tt = (Test) session.get("test.hibernate.Test", "name1_2");
System.out.println(tt.getName1()+" "+tt.getName2());
}catch(HibernateException e){
e.printStackTrace();
System.out.println(e.getMessages());
tr.rollback();
}finally{
session.close();
}
看一看控制台的输出
Hibernate: select test_.name1, test_.name2 as name2_0_, test_.datetime as datetime0_ from admintools.test test_ where test_.name1=?
-----------
Hibernate: select test0_.name1 as name1_0_0_, test0_.name2 as name2_0_0_, test0_.datetime as datetime0_0_ from admintools.test test0_ where test0_.name1=?
name1_2 name2_2
-----
name1_2 name2_2
我们可以看到第二次查询的时候并没有从数据库中查询。
Java开发Q群:46176507