项目中由于Ibatis自身的缓存的鸡肋性(Ibatis自身的缓存是查询字符串和相应的结果的缓存,效率非常有效并且很容易占用内存,采用大量的缓存时,Ibatis严重的影响效率),进行相应的扩展的采用OSCache进行对象缓存。
iBatis整理——EhCache支持扩展
项目完结,整理一些技术方面的相关收获。
已经记不得EhCacheController这个实现类最早来自于那里了,总之稍加修改后非常有效果,大家就这么用了,感谢最初开源的那位兄弟。这里,主要是做个记录,为以后类似扩展(譬如Memcached)做个准备。
iBatis提供CacheController接口,用于实现第三方缓存架构的扩展。
这里以iBatis 2.3.0,EhCache 1.2.3版本为基础,构建iBatis+EhCache实现。
EhCacheController类:
- package com.ibatis.sqlmap.engine.cache.ehcache;
- import java.net.URL;
- import java.util.Properties;
- import net.sf.ehcache.Cache;
- import net.sf.ehcache.CacheManager;
- import net.sf.ehcache.Element;
- import com.ibatis.sqlmap.engine.cache.CacheController;
- import com.ibatis.sqlmap.engine.cache.CacheModel;
- /**
- * EhCache Implementation of the
- * {@link com.ibatis.sqlmap.engine.cache.CacheController} interface to be able
- * to use EhCache as a cache implementation in iBatis. You can configure your
- * cache model as follows, by example, in your sqlMapping files:
- *
- * <pre>
- * <code>
- * <cacheModel id="myCache" readOnly="true" serialize="false"
- * type="com.ibatis.sqlmap.engine.cache.EhCacheController" >
- * <property name="configLocation"
- * value="/path-to-ehcache.xml"/>
- * </cacheModel> </code>
- * </pre>
- *
- * Alternatively, you can use a type alias in your type attribute and defining
- * the class with a <code><typeAlias></code> declaration:
- *
- * <pre>
- * <code>
- * <sqlMapConfig>
- * <typeAlias alias="EHCACHE"
- * type="com.ibatis.sqlmap.engine.cache.ehcache.EhCacheController" />
- * </sqlMapConfig>
- * </code>
- * </pre>
- *
- */
- public class EhCacheController implements CacheController {
- /**
- * The EhCache CacheManager.
- */
- private CacheManager cacheManager;
- public static final String CONFIG_LOCATION = "configLocation";
- /**
- * Default Configure Location
- */
- public static final String DEFAULT_CONFIG_LOCATION = "/ehcache.xml";
- /**
- * Flush a cache model.
- *
- * @param cacheModel
- * - the model to flush.
- */
- public void flush(CacheModel cacheModel) {
- getCache(cacheModel).removeAll();
- }
- /**
- * Get an object from a cache model.
- *
- * @param cacheModel
- * - the model.
- * @param key
- * - the key to the object.
- * @return the object if in the cache, or null(?).
- */
- public Object getObject(CacheModel cacheModel, Object key) {
- Object result = null;
- Element element = getCache(cacheModel).get(key);
- if (element != null) {
- result = element.getObjectValue();
- }
- return result;
- }
- /**
- * Put an object into a cache model.
- *
- * @param cacheModel
- * - the model to add the object to.
- * @param key
- * - the key to the object.
- * @param object
- * - the object to add.
- */
- public void putObject(CacheModel cacheModel, Object key, Object object) {
- getCache(cacheModel).put(new Element(key, object));
- }
- /**
- * Remove an object from a cache model.
- *
- * @param cacheModel
- * - the model to remove the object from.
- * @param key
- * - the key to the object.
- * @return the removed object(?).
- */
- public Object removeObject(CacheModel cacheModel, Object key) {
- Object result = this.getObject(cacheModel, key);
- getCache(cacheModel).remove(key);
- return result;
- }
- /**
- * Gets an EH Cache based on an iBatis cache Model.
- *
- * @param cacheModel
- * - the cache model.
- * @return the EH Cache.
- */
- private Cache getCache(CacheModel cacheModel) {
- String cacheName = cacheModel.getId();
- Cache cache = cacheManager.getCache(cacheName);
- return cache;
- }
- /**
- * Shut down the EH Cache CacheManager.
- */
- public void finalize() {
- if (cacheManager != null) {
- cacheManager.shutdown();
- }
- }
- /**
- * Configure a cache controller. Initialize the EH Cache Manager as a
- * singleton.
- *
- * @param props
- * - the properties object continaing configuration information.
- */
- @Override
- public void configure(Properties props) {
- String configLocation = props.getProperty(CONFIG_LOCATION);
- // if can not found ehcache.xml from configLocaion,
- // use default configure file.
- if (configLocation == null) {
- configLocation = DEFAULT_CONFIG_LOCATION;
- }
- URL url = getClass().getResource(configLocation);
- cacheManager = CacheManager.create(url);
- }
- }
这里默认在根目录下获取ehcache.xml文件,可以通过cacheModel配置进行修改。
在SqlMapConfig.xml文件中配置一个别名,作为全局变量,供其余SqlMap使用。
- <typeAlias
- alias="EHCACHE"
- type="com.ibatis.sqlmap.engine.cache.ehcache.EhCacheController" />
顺便提一句,要使用缓存注意SqlMapConfig.xml文件中settings节点配置cacheModelsEnabled为true!
- <settings
- cacheModelsEnabled="true"
- useStatementNamespaces="true"
- ...
- />
接下来,在SqlMap.xml文件中的cacheModel中
- <cacheModel
- id="cache"
- type="EHCACHE">
- ...
- </cacheModel>
如果要变更ehcache.xml文件路径为/config/ehcache.xml,可以在上述节点中下入如下代码:
- <property name="configLocation" value="/config/ehcache.xml" />
然后,就可以通过ehcache.xml控制ehcache缓存了!
举例说明iBatis SqlMap & ehcahce.xml,以免有些兄弟混淆!
以Account类为示例,在SqlMap中的配置为:
- <?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="Account">
- <cacheModel
- id="cache"
- type="EHCACHE">
- <flushInterval
- hours="1" />
- <!-- flush操作,需要指明 Namespace -->
- <flushOnExecute
- statement="Account.create" />
- </cacheModel>
- <typeAlias
- alias="account"
- type="org.zlex.acl.Account" />
- <resultMap
- id="accountMap"
- class="account">
- <result
- property="accountId"
- column="accountId" />
- <result
- property="accountName"
- column="accountName" />
- <result
- property="mail"
- column="mail" />
- <result
- property="realName"
- column="realName" />
- <result
- property="status"
- column="status" />
- <result
- property="lastLoginTime"
- column="lastLoginTime" />
- </resultMap>
- <select
- id="readByAccountName"
- parameterClass="string"
- resultMap="accountMap"
- cacheModel="cache">
- <![CDATA[
- SELECT
- accountId,
- accountName,
- mail,
- realName,
- status,
- lastLoginTime
- FROM
- acl_account
- WHERE
- accountName = #accountName#
- ]]>
- </select>
- <insert
- id="create"
- parameterClass="account">
- <![CDATA[
- INSERT INTO
- acl_account(
- accountName,
- mail,
- realName,
- status,
- lastLoginTime
- )
- VALUES (
- #accountName#,
- #mail#,
- #realName#,
- #status#,
- #lastLoginTime#
- )
- ]]>
- <selectKey
- resultClass="long"
- keyProperty="accountId">
- <![CDATA[select LAST_INSERT_ID() as id ]]>
- </selectKey>
- </insert>
- </sqlMap>
注意:
<select
id="readByAccountName"
parameterClass="string"
resultMap="accountMap"
cacheModel="cache">
这里的cacheModel="cache",对应的在ehcache.xml中就应该是:
- <cache
- name="Account.cache"
- maxElementsInMemory="10000"
- eternal="false"
- maxElementsOnDisk="1000"
- overflowToDisk="true"
- timeToIdleSeconds="300"
- />
因为,我使用了useStatementNamespaces="true"
package easyway.tbs.framework.cache;
import java.io.Serializable;
import java.util.Set;
/**
* cache 通用接口
*
* @author longgangbai
*/
publicinterface Cache extends Serializable {
public Object get(Object key);
publicvoid put(Object key, Object value);
publicvoid remove(Object key);
publicvoid clear();
publicint size();
@SuppressWarnings("unchecked")
public Set keys();
@SuppressWarnings("unchecked")
public Set values();
}
package easyway.tbs.framework.cache;
import easyway.tbs.framework.app.exceptions.SystemException;
/**
* CacheManager提供和维护Cache生命周期实例
*
* @authorlonggangbai
*/
publicinterface CacheManager {
/**
* 根据指定的名称获取Cache实现,
* 如果指定的名称的cache还不存,
* 则以名称建立一个cache
* 并返回cache对象
*
* @param name 要获得的cache名称.
* @return Cache 返回指定名称的cache实例
*/
public Cache getCache(String name) throws SystemException;
publicvoid destroy(String name) throws SystemException;
}
package easyway.tbs.framework.cache;
import java.util.HashMap;
import java.util.Map;
import easyway.tbs.framework.app.exceptions.SystemException;
/**
* 默认的内存缓存管理器
*
* @authorlonggangbai
*/
publicclass DefaultCacheManager implements CacheManager {
/**
* DefaultCacheManager维护内存缓存对象
*/
privatestaticfinal Map<String, Cache> caches = new HashMap<String, Cache>();
/*
* 获得指定的名称cache对象
*
* @see
* easyway.tbs.framework.app.cache.CacheManager#getCache(java.lang.String)
*/
public Cache getCache(String name) {
if (name == null) {
thrownew SystemException("cache-001", "缓存名称不能为空");
}
Cache cache;
synchronized (caches) {
cache = caches.get(name);
if (cache == null) {
cache = new SoftHashMapCache(name);
caches.put(name, cache);
}
}
return cache;
}
publicvoid destroy(String name) throws SystemException {
synchronized (caches) {
caches.remove(name);
}
}
}
项目建议:实现Ibatis的缓存的扩展建议采用mechcache或者xmechcache的分布式缓存功能,mechcache为分布式的缓存,性能各方面的比较优越。使用OSCache可以参考Spring或者Jforum中Cache的设计思路。
相关推荐
Ibatis 主要解决的问题是简化 JDBC 的繁琐工作,通过 XML 或注解方式配置 SQL 语句,使得业务逻辑和数据访问层之间有更好的解耦。 **核心概念** 1. **SqlMapConfig.xml**: 这是 Ibatis 的全局配置文件,包含了数据...
SSH2+IBATIS框架是Java开发中常用的一套企业级应用开发框架组合,它将Spring、Hibernate、Struts2和iBatis等组件融合在一起,以提高开发效率和实现松耦合。以下是对这些框架及其整合方式的详细说明: **Spring框架*...
SpringMvc和iBatis是Java开发中常用的两个框架,它们在Web应用开发中扮演着重要的角色。SpringMvc作为Spring框架的一部分,主要用于处理HTTP请求和视图的渲染,而iBatis则是一个轻量级的数据访问层框架,它将SQL与...
在这个自己编写的Ibatis框架实现中,我们可以看到类似的思路和核心功能。 1. **XML配置文件**: XML文件是Ibatis框架的核心,它存储了SQL语句、参数映射以及结果集映射等信息。在`sqlmap`目录下,可能包含了多个...
iBatis框架则提供了一种将SQL语句与Java代码分离的方式,通过XML配置文件或注解来定义SQL语句,使得数据库操作更易于维护和扩展。它的核心概念有SqlSessionFactory、SqlSession和Mapper。SqlSessionFactory创建...
Spring MVC 和 iBatis 是两个在 Java Web 开发中广泛使用的框架,它们组合起来可以构建高效、灵活且可维护的Web应用程序。Spring MVC 作为Spring框架的一部分,是用于构建前端控制器(DispatcherServlet)的MVC设计...
这个“struts2+spring+iBatis框架包”集成了这三个框架,使得开发者能够快速构建基于MVC(Model-View-Controller)模式的Web应用。 Struts2作为MVC框架,负责处理应用程序的控制逻辑。它通过Action类和配置文件定义...
3. iBatis框架:iBatis是一个SQL映射框架,它将SQL语句与Java代码分离,提供了一种灵活的方式来执行数据库操作。通过XML或注解方式定义SQL语句,iBatis可以动态地生成和执行SQL,避免了传统的JDBC代码繁琐的模板式...
Struts、Spring和iBatis是Java开发中常用的三大开源框架,它们各自负责应用程序的不同层面,共同构建了一个灵活且强大的企业级应用开发解决方案。这里,我们深入探讨这三个框架以及它们如何协同工作。 **Struts框架...
总的来说,Spring Struts iBatis框架组合提供了一个强大而灵活的开发环境,适合开发大型、复杂的企业级应用。通过熟练掌握这三个框架,开发者可以构建出符合现代开发标准的、易于维护的系统。在学习和使用过程中,...
《iBATIS框架源码剖析》这本书,作者任钢深入探讨了iBATIS的核心机制和实现原理,以下是对该框架的一些关键知识点的详细阐述。 1. **动态SQL**:iBATIS的一大亮点是它的动态SQL功能。通过在XML映射文件中使用条件...
通过对这些组件的源码阅读,我们可以学习到如何设计一个高效、可扩展的持久层框架,同时也可以借鉴Ibatis的优秀实践,比如它的动态SQL支持、缓存机制以及事务管理等。此外,源码中的异常处理、日志记录、单元测试等...
iBatis框架: 1. **SQL映射**:iBatis的核心是XML或注解方式定义的SQL语句,将SQL与Java代码分离,增强了可读性和维护性。 2. **动态SQL**:iBatis支持动态SQL,允许在SQL语句中根据条件动态生成不同的查询,提高...
本篇文章将深入探讨如何使用Ibatis框架实现对`student`表的增删改查操作,包括模糊查询以及利用序列自动生成主键。 首先,我们来理解Ibatis的基本概念。Ibatis是由Apache基金会维护的一个开源项目,它是一个SQL映射...
6. **良好的扩展性**:iBATIS允许开发者通过插件进行扩展,例如,可以通过拦截器实现日志记录、性能监控等功能。 7. **与各种数据库兼容**:iBATIS不绑定特定的数据库,可以方便地切换不同的数据库系统,适应不同的...
Ibatis框架是一个轻量级的Java持久层框架,它提供了SQL映射功能,将复杂的SQL语句与Java代码分离,使开发更为灵活高效。在这个"Ibatis框架三层架构项目"中,我们可以看到它按照标准的软件工程设计模式进行了分层,...
"struts2+spring+ibatis框架实例"是基于这三个框架的一个集成示例,它利用MySQL作为后端数据库。下面我们将详细探讨这三个框架及其在实际项目中的应用。 **Struts2框架** Struts2是MVC(模型-视图-控制器)架构模式...