在ibatis源码基础上修改,增加对memcached支持,通过配置IBatis的xml文件即可实现memcached细粒度话缓存,使用简单,缓 存效果好。 spring下首先初始化MemcachedManager对象,或者通过程序初始化也一样,不要用ibatis官方的jar包,否则会冲突
<bean class="com.ibatis.sqlmap.engine.cache.memcached.memcachedManager" lazy-init="false"
init-method="init" destroy-method="closePool">
<property name="serverlist">
<value>
192.168.0.1:11111, 192.168.0.2:11111
</value>
</property>
<property name="initConn" value="5"></property>
<property name="minConn" value="5"></property>
<property name="maxConn" value="200"></property>
Unknown end tag for </bean>
然后配置sqlMapConfig.xml文件: <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE sqlMapConfig PUBLIC "-//iBATIS.com//DTD SQL Map Config 2.0//EN"
"http://ibatis-with-memcached.googlecode.com/files/sql-map-config-2.dtd"> #注意这里,不用官方的,这个dtd文件加了个新属性databaseUrl,区分不同数据库的缓存对象
Java代码
- <properties resource="cache_config.properties"></properties>
<settings cacheModelsEnabled="true" enhancementEnabled="true" lazyLoadingEnabled="true"
maxRequests="256" maxSessions="256" maxTransactions="150" useStatementNamespaces="true"
databaseUrl="数据库名或地址" #新增加的属性 />
- ibatis的xml文件:Albums.xml #创建缓存model
- <cachemodel type="MEMCACHED" id="albumsCache">
<flushinterval hours="12"></flushInterval>
<flushonexecute statement="albums.save"></flushOnExecute>
<flushonexecute statement="albums.update"></flushOnExecute>
<flushonexecute statement="albums.delete"></flushOnExecute>
<property name="pk" value="id"></property>
#可以根据主键进行缓存,可以设置为空,不能不设
<property name="groupField" value="accId"></property>
#可以根据组(比如用户id)进行缓存,更加细粒度化,可以设置为空,不能不设
Unknown end tag for
</cachemodel>
-
- #加入缓存
- <select id="findall" parameterClass="albumsObj" resultClass="albumsObj" cacheModel="albumsCache">
Select ……from albums where accId=1
</select>
<select id="load" parameterClass="albumsObj" resultClass="albumsObj" cacheModel="albumsCache">
Select ……from albums where id=1
</select>
- 删除对象,删除缓存
<delete id="delete" parameterClass="albumsObj">
delete from albums where id=1 and accId=1 #(加上accId可以删除分组缓存)
</delete>
package com.ibatis.sqlmap.engine.cache.memcached;
import java.io.Serializable;
public class MemcachedManager {
private static Logger logger = Logger.getLogger(MemcachedManager.class);
private static String memcachedDomain = "IBATIS_CACHED"; // memcached 域名
private String serverlist;
private static MemCachedClient mcc = null;
private SockIOPool pool = null;
private int initConn = 5;
private int minConn = 5;
private int maxConn = 50;
public void init() {
if (mcc != null)
return;
logger.info("Initializing ibatis memcached start.");
if (pool == null) {
try {
pool = SockIOPool.getInstance(memcachedDomain);
pool.setServers(serverlist.split(","));
if (!pool.isInitialized()) {
pool.setInitConn(initConn);
pool.setMinConn(minConn);
pool.setMaxConn(maxConn);
pool.setMaintSleep(30);
pool.setNagle(false);
pool.setSocketTO(60 * 60);
pool.setSocketConnectTO(0);
pool.initialize();
}
} catch (Exception ex) {
logger.error(ex.getMessage());
}
}
if (mcc == null) {
mcc = new MemCachedClient(memcachedDomain);
mcc.setCompressEnable(false);
mcc.setCompressThreshold(0);
}
logger.info("Initializing youxigu Memcached ok!");
}
public void closePool() {
pool.shutDown();
mcc = null;
pool = null;
logger.info("Ibatis memcached pool closed");
}
public static boolean set(Object key, Serializable obj) {
logger.debug("set key:" + getKey(key) + ", value:" + obj);
try {
return mcc.set(getKey(key), obj);
} catch (Exception e) {
logger.error("Pool set error!");
e.printStackTrace();
}
return false;
}
public static boolean set(Object key, Serializable obj, long cacheTime) {
try {
return mcc.set(getKey(key), obj, new Date(cacheTime));
} catch (Exception e) {
logger.error("Pool set error!");
e.printStackTrace();
}
return false;
}
public static void replace(int key, Serializable value, long cacheTime) {
try {
mcc.replace(getKey(key), value, new Date(cacheTime));
} catch (Exception e) {
logger.error(" pool set error!");
}
}
public static Object get(Object key) {
Object result = null;
String realkey = getKey(key);
try {
result = mcc.get(realkey);
} catch (Exception e) {
e.printStackTrace();
}
logger.debug("get key:" + getKey(key) + ", value:" + result);
return result;
}
public static void setCounter(Object key, long count) {
try {
mcc.storeCounter(getCountKey(key), count);
} catch (Exception e) {
logger.error("Pool setCounter error!");
}
}
public static void addCounter(Object key) {
if (mcc.get(getCountKey(key)) == null) {
mcc.storeCounter(getCountKey(key), 0);
}
try {
mcc.incr(getCountKey(key));
} catch (Exception e) {
logger.error("Pool setCounter error!");
}
}
public static void decreaseCounter(Object key) {
try {
mcc.decr(getCountKey(key));
} catch (Exception e) {
logger.error("Pool setCounter error!");
}
}
public static void addCounter(Object key, long addValue) {
try {
mcc.incr(getCountKey(key), addValue);
} catch (Exception e) {
logger.error(" pool setCounter error!");
}
}
public static long getCounter(Object key) {
long result = 0;
try {
result = mcc.getCounter(getCountKey(key));
} catch (Exception e) {
logger.error(e.getMessage());
}
return result;
}
public static boolean delete(Object key) {
try {
return mcc.delete(getKey(key));
} catch (Exception e) {
logger.error(e.getMessage());
}
return false;
}
public static long deleteCounter(Object key) {
try {
return mcc.decr(getCountKey(key));
} catch (Exception e) {
logger.error(" pool setCounter error!");
}
return 0;
}
public static void flushAll() {
mcc.flushAll();
}
@SuppressWarnings("unchecked")
public static long size() {
long size = 0L;
Map<String, Map<String, String>> status = mcc.statsItems();
Collection<Map<String, String>> values = status.values();
for (Map<String, String> state : values) {
String num = state.get("items:1:number");
if (num == null)
continue;
size += Long.parseLong(state.get("items:1:number"));
}
return size;
}
private static String getKey(Object key) {
return memcachedDomain + "@" + key;
}
private static String getCountKey(Object key) {
return memcachedDomain + "@" + key + "_count";
}
public void setServerlist(String serverlist) {
this.serverlist = serverlist;
}
public void setInitConn(int initConn) {
this.initConn = initConn;
}
public void setMinConn(int minConn) {
this.minConn = minConn;
}
public void setMaxConn(int maxConn) {
this.maxConn = maxConn;
}
public void setMemcachedDomain(String memcachedKey) {
MemcachedManager.memcachedDomain = memcachedKey;
}
}
源文:http://jwen.iteye.com/blog/1123985