最近项目需用Redis来实现Mybatis缓存方案。
mybatis默认缓存是PerpetualCache,可以查看一下它的源码,发现其是Cache接口的实现;那么我们的缓存只要实现该接口即可。
该接口有以下方法需要实现:
String getId();
int getSize();
void putObject(Object key, Object value);
Object getObject(Object key);
Object removeObject(Object key);
void clear();
ReadWriteLock getReadWriteLock();
实现类:
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.apache.ibatis.cache.Cache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
public class MybatisRedisCache implements Cache {
private static Logger logger = LoggerFactory.getLogger(MybatisRedisCache.class);
private Jedis redisClient=createReids();
/** The ReadWriteLock. */
private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
private String id;
public MybatisRedisCache(final String id) {
if (id == null) {
throw new IllegalArgumentException("Cache instances require an ID");
}
logger.debug(">>>>>>>>>>>>>>>>>>>>>>>>MybatisRedisCache:id="+id);
this.id = id;
}
@Override
public String getId() {
return this.id;
}
@Override
public int getSize() {
return Integer.valueOf(redisClient.dbSize().toString());
}
@Override
public void putObject(Object key, Object value) {
logger.debug(">>>>>>>>>>>>>>>>>>>>>>>>putObject:"+key+"="+value);
redisClient.set(SerializeUtil.serialize(key.toString()), SerializeUtil.serialize(value));
}
@Override
public Object getObject(Object key) {
Object value = SerializeUtil.unserialize(redisClient.get(SerializeUtil.serialize(key.toString())));
logger.debug(">>>>>>>>>>>>>>>>>>>>>>>>getObject:"+key+"="+value);
return value;
}
@Override
public Object removeObject(Object key) {
return redisClient.expire(SerializeUtil.serialize(key.toString()),0);
}
@Override
public void clear() {
redisClient.flushDB();
}
@Override
public ReadWriteLock getReadWriteLock() {
return readWriteLock;
}
protected static Jedis createReids(){
JedisPool pool = new JedisPool(new JedisPoolConfig(), "10.12.162.85");
return pool.getResource();
}
public class SerializeUtil {
public static byte[] serialize(Object object) {
ObjectOutputStream oos = null;
ByteArrayOutputStream baos = null;
try {
//序列化
baos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(baos);
oos.writeObject(object);
byte[] bytes = baos.toByteArray();
return bytes;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static Object unserialize(byte[] bytes) {
ByteArrayInputStream bais = null;
try {
//反序列化
bais = new ByteArrayInputStream(bytes);
ObjectInputStream ois = new ObjectInputStream(bais);
return ois.readObject();
} catch (Exception e) {
}
return null;
}
配置Mybatis SessionFactory:
<!-- SessionFactory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configurationProperties">
<props>
<prop key="cacheEnabled">true</prop>
<!-- 查询时,关闭关联对象即时加载以提高性能 -->
<prop key="lazyLoadingEnabled">true</prop>
<!-- 设置关联对象加载的形态,此处为按需加载字段(加载字段由SQL指 定),不会加载关联表的所有字段,以提高性能 -->
<prop key="aggressiveLazyLoading">false</prop>
<!-- 对于未知的SQL查询,允许返回不同的结果集以达到通用的效果 -->
<prop key="multipleResultSetsEnabled">true</prop>
<!-- 允许使用列标签代替列名 -->
<prop key="useColumnLabel">true</prop>
<!-- 允许使用自定义的主键值(比如由程序生成的UUID 32位编码作为键值),数据表的PK生成策略将被覆盖 -->
<prop key="useGeneratedKeys">true</prop>
<!-- 给予被嵌套的resultMap以字段-属性的映射支持 -->
<prop key="autoMappingBehavior">FULL</prop>
<!-- 对于批量更新操作缓存SQL以提高性能 -->
<prop key="defaultExecutorType">BATCH</prop>
<!-- 数据库超过25000秒仍未响应则超时 -->
<prop key="defaultStatementTimeout">25000</prop>
</props>
</property>
</bean>
最后在需要缓存的DAO类上添加@CacheNamespace(implementation=MybatisRedisCache.class )
这样就完成了Mybatis自定义缓存的实现。
参考文件:1、http://denger.iteye.com/blog/1126423
2、MyBatis 3 User Guide