`
jasonw68
  • 浏览: 149891 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

ibatis 缓存实例

 
阅读更多

缓存,顾名思义,就是将从数据库中查询出来的数据在某个缓冲区域暂时保存起来,在需要数据的时候从该缓冲区中读取,而不是从数据库中读取,从而减少对数据库访问次数,达到减少系统开销,提高性能的目的。

在本文中,我将结合实例讲述ibatis的缓存使用及相关原理。

首先我们来看一个ibatis应用所需要的配置文件:
(注:由于我们只关注ibatis的缓存,所以在ibatis的配置文件中我们只讨论与缓存相关的配置,其它的配置我们将省略!)

1.sql-map的配置,查看配置文件的dtd声明:

<!ELEMENT sqlMap (typeAlias* | cacheModel* | resultMap* | parameterMap* | sql* | statement* | insert* | update* | delete* | select* | procedure*)+>

以上是sql-map配置文件可以使用的元素,其中有些元素还有子元素及属性,这些都可以通过查看ibatis的dtd文件来知晓。在这个dtd声明中有一个cacheModel元素特别耀眼,相信读者已经猜测出来了,的确,该元素即为缓存模型,再看看该元素的子元素及属性:

<!ELEMENT cacheModel (flushInterval?, flushOnExecute*, property*)+>
<!ATTLIST cacheModel
id CDATA #REQUIRED
type CDATA #REQUIRED
readOnly (true | false) #IMPLIED
serialize (true | false) #IMPLIED
>

再看每个子元素的相关属性:

<!ELEMENT flushInterval EMPTY>
<!ATTLIST flushInterval
milliseconds CDATA #IMPLIED
seconds CDATA #IMPLIED
minutes CDATA #IMPLIED
hours CDATA #IMPLIED
>
<!ELEMENT flushOnExecute EMPTY>
<!ATTLIST flushOnExecute
statement CDATA #REQUIRED
>
<!ELEMENT property EMPTY>
<!ATTLIST property
name CDATA #REQUIRED
value CDATA #REQUIRED
>

于是,通过查看ibatis的dtd声明,我们即可得知在ibatis中是如何配置缓存管理的,将以上信息连接起来即可得到如下一段配置:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMap
PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"
"http://ibatis.apache.org/dtd/sql-map-2.dtd">
<sqlMap namespace="User">
<cacheModel id="user-cache" type ="LRU" readOnly="true" serialize="false">
<flushInterval hours="24"/>
<flushOnExecute statement=” updateUser”/>
<flushOnExecute statement="insertUser"/>
<flushOnExecute statement="deleteUser"/>
<property value="500" name="size"/>
</cacheModel>
<!―其他配置信息 -->
。。。。。。。。。。
</sqlMap>

那么这些配置都是什么含义呢?继续:
id:一个标识,在下面的select语句中将引用该标识。

Type: cacheModel的实现类型,目前有如下4种实现:
(1). "MEMORY” (com.ibatis.sqlmap.engine.cache.memory.MemoryCacheController) ,MEMORY cache 实现使用java的软引用类型来管理cache 的行为,使用一个HashMap来保存当前需要缓存的数据对象的引用,当内存不足时,java虚拟机将回收这些引用,从而清除cache。
(2).“LRU” (com.ibatis.sqlmap.engine.cache.lru.LruCacheController) ,LRU Cache 实现用“近期最少使用”原则来确定如何从Cache中清除对象,当Cache溢出时,最近最少使用的对象将被从Cache中清除。
(3).“FIFO” (com.ibatis.sqlmap.engine.cache.fifo.FifoCacheController) ,FIFO Cache 实现用“先进先出”原则来确定如何从 Cache 中清除对象。即最先进入 Cache 的对象将从 Cache 中清除。
(4).“OSCACHE” (com.ibatis.sqlmap.engine.cache.oscache.OSCacheController) ,OSCACHE Cache 实现是OSCache2.0缓存引擎的一个Plugin,它具有高度的可配置性,分布式,高度的灵活性(很推荐使用该类型)OSCache可以通过oscache.properties文件进行缓存的相关配置。

readOnly:readOnly的值表示缓存中的数据对象是否只读。若为true,则当数据对象发生变化时,数据对象就将被从缓存中废除,下次需要重新从数据库读取数据,构造新的数据对象。而若为false,则意味着缓存中的数据对象可更新,不必从数据库中读取。

serialize:如果需要全局的数据缓存,CacheModel的serialize属性必须被设为true。否则数据缓存只对当前Session有效,局部缓存对系统的整体性能提升有限。在serialize="true"的情况下,如果有多个Session同时从Cache 中读取某个数据对象,Cache将为每个Session返回一个对象的复本,也就是说,每个Session将得到包含相同信息的不同对象实例。因而Session可以对其从Cache获得的数据进行存取而无需担心多线程并发情况下的同步冲突。

<flushInterval hours=”24”>:指定多长时间清除缓存,例如指定每24小时强行清空缓存区的所有内容。

<flushOnExecute statement="insertUser"/>:在执行指定的语句时将刷新数据库。

Size:指定Cache的最大容量。

通过在一个SQL Map XML file配置以上信息,我们就可以在一个查询中使用该缓存管理,配置如下:

<select resultMap="UserResult" cacheModel=”user-cache”>
select * from USER
</select>

2.sql-map-config的配置,查看配置文件的dtd声明:

<!ELEMENT sqlMapConfig (properties?, settings?, resultObjectFactory?, typeAlias*, typeHandler*, transactionManager?, sqlMap+)+>

在这个dtd的声明中,有一个settings元素,通过继续查看该元素的属性

<!ELEMENT settings EMPTY>
<!ATTLIST settings
classInfoCacheEnabled (true | false) #IMPLIED
lazyLoadingEnabled (true | false) #IMPLIED
statementCachingEnabled (true | false) #IMPLIED
cacheModelsEnabled (true | false) #IMPLIED
enhancementEnabled (true | false) #IMPLIED
errorTracingEnabled (true | false) #IMPLIED
useStatementNamespaces (true | false) #IMPLIED
useColumnLabel (true | false) #IMPLIED
forceMultipleResultSetSupport (true | false) #IMPLIED
maxSessions CDATA #IMPLIED
maxTransactions CDATA #IMPLIED
maxRequests CDATA #IMPLIED
defaultStatementTimeout CDATA #IMPLIED
>

显然,属性cacheModelsEnabled就表示是否启用SqlMapClient上的缓存机制。将其设为"true"则标识启用缓存机制,反之则不启用。

通过上面对两个配置文件的分析,我们已经对在ibatis中如何使用缓存有了大致的了解和认识,下面我们将通过一个实例来演示ibatis缓存的使用并检验ibatis的缓存是否已经起作用。

我们的测试方法如下:
1.将数据库中预先插入一些数据(通过控制台或数据库客户端插入数据),然后利用编写好的程序访问数据库,第一次访问数据库时将查询出所有的数据,但当我们通过控制台或数据库客户端(如mysql客户端)再向数据库中插入一些数据,这时再通过编写好的程序去访问数据库,发现通过控制台或数据库客户端新插入的数据并没有被查询出来,说明ibatis读取的是第一次查询所保存在缓存中的数据,这说明测试成功!
2.当我们使用程序而不是控制台或客户端再向数据库插入数据,同时又通过程序访问数据库时,新插入数据库的数据都被查询了出来,而不是从缓存中读取,这说明测试成功,因为我们配置了<flushOnExecute statement="insertUser" />当插入数据时将刷新数据库。

下面就开始我们的测试:
1.建立一个web工程,导入相关的jar包;
2.编写具体代码;
3.做缓存测试;

sql-map文件的配置:User.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMap
PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"
"http://ibatis.apache.org/dtd/sql-map-2.dtd">

<sqlMap namespace="User">
<typeAlias alias="User" type="com.javaeye.hnylj.model.User" />

<!-- 配置缓存模型 -->
<cacheModel id="user-cache" type="OSCache" readOnly="true"
serialize="true">
<flushInterval hours="24" />
<flushOnExecute statement="insertUser" />
<property value="500" name="size" />
</cacheModel>

<resultMap >
<result property="id" column="ID" />
<result property="name" column="NAME" />
<result property="age" column="AGE" />
</resultMap>

<select resultMap="UserResult"
cacheModel="user-cache">
SELECT * FROM USER
</select>

<insert parameterClass="User">
INSERT INTO USER ( NAME, AGE, PASSWORD) VALUES ( #name#, #age#, #password# )
</insert>

</sqlMap>

sql-map-config文件的配置: SqlMapConfig.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMapConfig
PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN"
"http://ibatis.apache.org/dtd/sql-map-config-2.dtd">

<sqlMapConfig>

<settings lazyLoadingEnabled="true" cacheModelsEnabled="true"
maxSessions="30" maxTransactions="100" maxRequests="1000"
defaultStatementTimeout="15" />

<transactionManager type="JDBC" commitRequired="false">
<dataSource type="SIMPLE">
<property name="JDBC.Driver" value="com.mysql.jdbc.Driver" />
<property name="JDBC.ConnectionURL"
value="jdbc:mysql://127.0.0.1:3306/ibatis" />
<property name="JDBC.Username" value="root" />
<property name="JDBC.Password" value="123" />
</dataSource>
</transactionManager>

<sqlMap resource="com/javaeye/hnylj/model/User.xml" />

</sqlMapConfig>

接下来就是编写DAO,Action以及jsp页面,在这里,Action层使用了struts2。

Dao代码:UserDAO

package com.javaeye.hnylj.dao;

import java.io.IOException;
import java.io.Reader;
import java.sql.SQLException;
import java.util.List;

import com.ibatis.common.resources.Resources;
import com.ibatis.sqlmap.client.SqlMapClient;
import com.ibatis.sqlmap.client.SqlMapClientBuilder;
import com.javaeye.hnylj.model.User;

public class UserDAO {

private static SqlMapClient sqlMapper;

static {
try {
Reader reader = Resources.getResourceAsReader("com/javaeye/hnylj/model/SqlMapConfig.xml");
sqlMapper = SqlMapClientBuilder.buildSqlMapClient(reader);
reader.close();
} catch (IOException e) {
throw new RuntimeException("building the SqlMapClient instance error."+ e, e);
}
}

public List<?> getAllUser() throws SQLException {
List<?> list = sqlMapper.queryForList("selectAllUser");
System.out.println(list.size());
return list;
}

public void insertUser(User user) throws SQLException {
sqlMapper.insert("insertUser", user);
}
}

Action代码:UserAction

package com.javaeye.hnylj.action;

import java.util.List;

import com.javaeye.hnylj.dao.UserDAO;
import com.javaeye.hnylj.model.User;
import com.opensymphony.xwork2.ActionSupport;

public class UserAction extends ActionSupport {

private static final long serialVersionUID = 4689260572038875931L;
private UserDAO userDAO;
private List<User> userList;

private Integer id;
private String name;
private Integer age;
private String password;

public Integer getId() {
return id;
}

public void setId(Integer id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Integer getAge() {
return age;
}

public void setAge(Integer age) {
this.age = age;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

public List<User> getUserList() {
return userList;
}

public void setUserList(List<User> userList) {
this.userList = userList;
}

public String findAllUsers() throws Exception {
userDAO = new UserDAO();
userList = (List<User>)userDAO.getAllUser();
if (userList.size() > 0) {
return SUCCESS;
}
return ERROR;
}

public String add() throws Exception {
userDAO = new UserDAO();
User user = new User();
user.setName(name);
user.setAge(age);
user.setPassword(password);
userDAO.insertUser(user);
return SUCCESS;
}
}

还有其他一些代码或配置,在此省略!

将工程部署成功以后,按照上面的测试方法即可进行测试!

分享到:
评论

相关推荐

    iBATIS实战

    书中既详实地介绍了iBATIS的设计理念和基础知识,也讨论了动态SQL、高速缓存、DAD框架等高级主题,还讲解了iBATIS在实际开发中的应用。书的最后给出了一个设计优雅、层次清晰的示例程序JGameStore,该示例涵盖全书的...

    springMVC_ibatis_redis_cxf_restful框架整合代码实例

    1.简单的ibatis多表级联 2.基于cxf的restful接口开发,包括文件上传(文档,图片等)接口 3.redis缓存服务,通过spring的aop来控制 4.file表太大,我给清空了,测试的是注意报错 5.本人测试通过,有问题可交流

    ibatis 开发指南(pdf)

    ibatis 实例配置 一个典型的配置文件如下(具体配置项目的含义见后): &lt;?xml version="1.0" encoding="UTF-8" ?&gt; &lt;!DOCTYPE sqlMapConfig PUBLIC "-//iBATIS....

    spring 3.0 jar 所有开发包及开发项目实例

    spring 3.0 jar 最新所有开发包及开发项目实例 spring 3.0已经全面支持OSGi了。 各发行包的大致描述如下: org.springframework.asm-3.0.0.M4.jar: 提供对ASM(一个字节码框架)的简单封装 org.springframework....

    Spring 2.5 jar 所有开发包及完整文档及项目开发实例

    Spring 2.5 jar 所有开发包及完整文档及项目开发实例 spring jar 包详解spring.jar是包含有完整发布的单个jar包,spring.jar中包含除了 spring-mock.jar里所包含的内容外其它所有jar包的内容,因为只有在开发环境下...

    Python ORM编程基础示例

    本文实例讲述了Python ORM编程。分享给大家供大家参考,具体如下: ORM编程 ORM(object-relational mapping)对象关系映射 作用:在关系型数据库和业务实体对象之间做一个映射,方便在开发中,不需要再使用复杂的...

    Spring面试题

    ☆ Spring ORM:Spring 框架插入了若干个 ORM 框架,从而提供了 ORM 的对象关系工具,其中包括 JDO、Hibernate 和 iBatis SQL Map。所有这些都遵从 Spring 的通用事务和 DAO 异常层次结构。 ☆ Spring Web 模块:...

    Spring-Reference_zh_CN(Spring中文参考手册)

    8.3.1. Context管理和缓存 8.3.2. 测试fixture的依赖注入 8.3.3. 事务管理 8.3.4. 方便的变量 8.3.5. 示例 8.3.6. 运行集成测试 8.4. 更多资源 II. 中间层数据访问 9. 事务管理 9.1. 简介 9.2. 动机 9.3. 关键抽象 ...

    spring chm文档

    8.3.1. Context管理和缓存 8.3.2. 测试fixture的依赖注入 8.3.3. 事务管理 8.3.4. 方便的变量 8.3.5. 示例 8.3.6. 运行集成测试 8.4. 更多资源 II. 中间层数据访问 9. 事务管理 9.1. 简介 9.2. 动机 9.3....

    Spring 2.0 开发参考手册

    8.3.1. Context管理和缓存 8.3.2. 测试fixture的依赖注入 8.3.3. 事务管理 8.3.4. 方便的变量 8.3.5. 示例 8.3.6. 运行集成测试 8.4. 更多资源 II. 中间层数据访问 9. 事务管理 9.1. 简介 9.2. 动机 9.3....

    jfinalpluginsjfinal-dreampie.zip

    11.QuartzPlugin使用quartz执行定时任务,参照部分网络实例,简易实现 QuartzFactory.me().startJobOnce(TimeUtils.me().toString(DateTime.now()), jobId, "stati", this.getClass().getSimpleName(), ...

    Java面试宝典2010版

    17.介绍一下Hibernate的二级缓存 18、Spring 的依赖注入是什么意思? 给一个 Bean 的 message 属性, 字符串类型, 注入值为 "Hello" 的 XML 配置文件该怎么写? 19、Jdo是什么? 20、什么是spring的IOC AOP 21、...

    最新Java面试宝典pdf版

    17.介绍一下Hibernate的二级缓存 123 18、Spring 的依赖注入是什么意思? 给一个 Bean 的 message 属性, 字符串类型, 注入值为 "Hello" 的 XML 配置文件该怎么写? 125 19、Jdo是什么? 125 20、什么是spring的IOC AOP ...

    Java面试笔试资料大全

    17.介绍一下Hibernate的二级缓存 123 18、Spring 的依赖注入是什么意思? 给一个 Bean 的 message 属性, 字符串类型, 注入值为 "Hello" 的 XML 配置文件该怎么写? 125 19、Jdo是什么? 125 20、什么是spring的IOC AOP ...

    JAVA面试宝典2010

    17.介绍一下Hibernate的二级缓存 123 18、Spring 的依赖注入是什么意思? 给一个 Bean 的 message 属性, 字符串类型, 注入值为 "Hello" 的 XML 配置文件该怎么写? 125 19、Jdo是什么? 125 20、什么是spring的IOC AOP ...

    Java面试宝典-经典

    17.介绍一下Hibernate的二级缓存 123 18、Spring 的依赖注入是什么意思? 给一个 Bean 的 message 属性, 字符串类型, 注入值为 "Hello" 的 XML 配置文件该怎么写? 125 19、Jdo是什么? 125 20、什么是spring的IOC AOP ...

    java面试题大全(2012版)

    17.介绍一下Hibernate的二级缓存 123 18、Spring 的依赖注入是什么意思? 给一个 Bean 的 message 属性, 字符串类型, 注入值为 "Hello" 的 XML 配置文件该怎么写? 125 19、Jdo是什么? 125 20、什么是spring的IOC AOP ...

    Java面试宝典2012版

    17.介绍一下Hibernate的二级缓存 123 18、Spring 的依赖注入是什么意思? 给一个 Bean 的 message 属性, 字符串类型, 注入值为 "Hello" 的 XML 配置文件该怎么写? 125 19、Jdo是什么? 125 20、什么是spring的IOC ...

    java面试宝典2012

    17.介绍一下Hibernate的二级缓存 135 18、Spring 的依赖注入是什么意思? 给一个 Bean 的 message 属性, 字符串类型, 注入值为 "Hello" 的 XML 配置文件该怎么写? 137 19、Jdo是什么? 137 20、什么是spring的IOC AOP ...

Global site tag (gtag.js) - Google Analytics