mybatis通过配置文件方式整合redis缓存,替换mybatis二级缓存
来源:互联网 发布:网络棋牌游戏赌博平台 编辑:程序博客网 时间:2024/05/18 22:09
mybatis通过redis取代二级缓存,二级缓存的缺点不再赘述。
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();
下面开始实现代码
==============================华丽的分割线========================
1,RedisCache实现类
import org.apache.ibatis.cache.Cache;import redis.clients.jedis.Jedis;import redis.clients.jedis.JedisPool;/** * Cache adapter for Redis. * * @author Eduardo Macarron */public final class RedisCache implements Cache { private static JedisPool pool; private final ReadWriteLock readWriteLock = new DummyReadWriteLock(); private final String id; private final Integer expireSeconds; public RedisCache(final String id) { if (id == null) { throw new IllegalArgumentException("Cache instances require an ID"); } this.id = id; final RedisConfig redisConfig = RedisConfigurationBuilder.getInstance().parseConfiguration(); pool = new JedisPool(redisConfig, redisConfig.getHost(), redisConfig.getPort(), redisConfig.getConnectionTimeout(), redisConfig.getSoTimeout(), redisConfig.getPassword(), redisConfig.getDatabase(), redisConfig.getClientName()); expireSeconds = redisConfig.getSettings().get(id) * 60; } @Override public void clear() { execute(new RedisCallback() { @Override public Object doWithRedis(Jedis jedis) { // jedis.del(id.toString()); throw new UnsupportedOperationException("not support redis-cache getsize method."); // return null; } }); } private Object execute(RedisCallback callback) { final Jedis jedis = pool.getResource(); try { return callback.doWithRedis(jedis); } finally { jedis.close(); } } @Override public String getId() { return this.id; } @Override public Object getObject(final Object key) { return execute(new RedisCallback() { @Override public Object doWithRedis(Jedis jedis) { // return SerializeUtil.unserialize(jedis.hget(id.toString().getBytes(), // key.toString().getBytes())); return SerializeUtil.unserialize(jedis.get(key.toString().getBytes())); } }); } @Override public ReadWriteLock getReadWriteLock() { return readWriteLock; } @Override public int getSize() { return (Integer) execute(new RedisCallback() { @Override public Object doWithRedis(Jedis jedis) { throw new UnsupportedOperationException("not support redis-cache getsize method."); } }); } @Override public void putObject(final Object key, final Object value) { execute(new RedisCallback() { @Override public Object doWithRedis(Jedis jedis) { System.out.println("缓存----------------:" + key); jedis.set(key.toString().getBytes(), SerializeUtil.serialize(value)); if (expireSeconds > 0) { jedis.expire(key.toString().getBytes(), expireSeconds); } // jedis.hset(id.toString().getBytes(), key.toString().getBytes(), // SerializeUtil.serialize(value)); return null; } }); } @Override public Object removeObject(final Object key) { return execute(new RedisCallback() { @Override public Object doWithRedis(Jedis jedis) { // return jedis.hdel(id.toString(), key.toString()); // return jedis.del(key.toString()); throw new UnsupportedOperationException("not support redis-cache getsize method."); } }); } @Override public String toString() { return "Redis {" + id + "}"; }}2,DummyReadWriteLock 类
import java.util.concurrent.TimeUnit;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReadWriteLock;/** * @author Iwao AVE! */class DummyReadWriteLock implements ReadWriteLock { static class DummyLock implements Lock { @Override public void lock() { // Not implemented } @Override public void lockInterruptibly() throws InterruptedException { // Not implemented } @Override public Condition newCondition() { return null; } @Override public boolean tryLock() { return true; } @Override public boolean tryLock(long paramLong, TimeUnit paramTimeUnit) throws InterruptedException { return true; } @Override public void unlock() { // Not implemented } } private final Lock lock = new DummyLock(); @Override public Lock readLock() { return lock; } @Override public Lock writeLock() { return lock; }}3,RedisCallback 接口
import redis.clients.jedis.Jedis;public interface RedisCallback { Object doWithRedis(Jedis jedis);}
4,RedisConfig 类
import java.util.Hashtable;import redis.clients.jedis.JedisPoolConfig;import redis.clients.jedis.Protocol;public class RedisConfig extends JedisPoolConfig { private String host = Protocol.DEFAULT_HOST; private int port = Protocol.DEFAULT_PORT; private int connectionTimeout = Protocol.DEFAULT_TIMEOUT; private int soTimeout = Protocol.DEFAULT_TIMEOUT; private String password; private int database = Protocol.DEFAULT_DATABASE; private String clientName; private final Hashtable<String, Integer> settings = new Hashtable<String, Integer>(); public String getClientName() { return clientName; } public int getConnectionTimeout() { return connectionTimeout; } public int getDatabase() { return database; } public String getHost() { return host; } public String getPassword() { return password; } public int getPort() { return port; } public Hashtable<String, Integer> getSettings() { return settings; } public int getSoTimeout() { return soTimeout; } public void setClientName(String clientName) { if ("".equals(clientName)) { clientName = null; } this.clientName = clientName; } public void setConnectionTimeout(int connectionTimeout) { this.connectionTimeout = connectionTimeout; } public void setDatabase(int database) { this.database = database; } public void setHost(String host) { if (host == null || "".equals(host)) { host = Protocol.DEFAULT_HOST; } this.host = host; } public void setPassword(String password) { if ("".equals(password)) { password = null; } this.password = password; } public void setPort(int port) { this.port = port; } public void setSoTimeout(int soTimeout) { this.soTimeout = soTimeout; }}5,RedisConfigurationBuilder 类
import java.io.IOException;import java.io.InputStream;import java.util.Map;import java.util.Properties;import org.apache.ibatis.cache.CacheException;import org.apache.ibatis.reflection.MetaObject;import org.apache.ibatis.reflection.SystemMetaObject;/** * Converter from the Config to a proper {@link RedisConfig}. * * @author Eduardo Macarron */final class RedisConfigurationBuilder { /** * This class instance. */ private static final RedisConfigurationBuilder INSTANCE = new RedisConfigurationBuilder(); private static final String SYSTEM_PROPERTY_REDIS_PROPERTIES_FILENAME = "redis.properties.filename"; private static final String REDIS_RESOURCE = "redis.properties"; /** * Return this class instance. * * @return this class instance. */ public static RedisConfigurationBuilder getInstance() { return INSTANCE; } private final String redisPropertiesFilename; /** * Hidden constructor, this class can't be instantiated. */ private RedisConfigurationBuilder() { redisPropertiesFilename = System.getProperty(SYSTEM_PROPERTY_REDIS_PROPERTIES_FILENAME, REDIS_RESOURCE); } private boolean isInteger(String s) { return isInteger(s, 10); } private boolean isInteger(String s, int radix) { if (s.isEmpty()) { return false; } for (int i = 0; i < s.length(); i++) { if (i == 0 && s.charAt(i) == '-') { if (s.length() == 1) { return false; } else { continue; } } if (Character.digit(s.charAt(i), radix) < 0) { return false; } } return true; } /** * Parses the Config and builds a new {@link RedisConfig}. * * @return the converted {@link RedisConfig}. */ public RedisConfig parseConfiguration() { return parseConfiguration(getClass().getClassLoader()); } /** * Parses the Config and builds a new {@link RedisConfig}. * * @param the * {@link ClassLoader} used to load the {@code memcached.properties} * file in classpath. * @return the converted {@link RedisConfig}. */ public RedisConfig parseConfiguration(ClassLoader classLoader) { final Properties config = new Properties(); final InputStream input = classLoader.getResourceAsStream(redisPropertiesFilename); if (input != null) { try { config.load(input); } catch (final IOException e) { throw new RuntimeException("An error occurred while reading classpath property '" + redisPropertiesFilename + "', see nested exceptions", e); } finally { try { input.close(); } catch (final IOException e) { // close quietly } } } final RedisConfig jedisConfig = new RedisConfig(); jedisConfig.setHost("localhost"); setConfigProperties(config, jedisConfig); return jedisConfig; } private void setConfigProperties(Properties properties, RedisConfig jedisConfig) { if (properties != null) { final MetaObject metaCache = SystemMetaObject.forObject(jedisConfig); for (final Map.Entry<Object, Object> entry : properties.entrySet()) { final String name = (String) entry.getKey(); final String value = (String) entry.getValue(); if (metaCache.hasSetter(name)) { final Class<?> type = metaCache.getSetterType(name); if (String.class == type) { metaCache.setValue(name, value); } else if (int.class == type || Integer.class == type) { metaCache.setValue(name, Integer.valueOf(value)); } else if (long.class == type || Long.class == type) { metaCache.setValue(name, Long.valueOf(value)); } else if (short.class == type || Short.class == type) { metaCache.setValue(name, Short.valueOf(value)); } else if (byte.class == type || Byte.class == type) { metaCache.setValue(name, Byte.valueOf(value)); } else if (float.class == type || Float.class == type) { metaCache.setValue(name, Float.valueOf(value)); } else if (boolean.class == type || Boolean.class == type) { metaCache.setValue(name, Boolean.valueOf(value)); } else if (double.class == type || Double.class == type) { metaCache.setValue(name, Double.valueOf(value)); } else { throw new CacheException("Unsupported property type: '" + name + "' of type " + type); } } else if (isInteger(value)) { jedisConfig.getSettings().put(name, Integer.parseInt(value)); } } } }}6,SerializeUtil 类
import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import org.apache.ibatis.cache.CacheException;public final 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); final byte[] bytes = baos.toByteArray(); return bytes; } catch (final Exception e) { throw new CacheException(e); } } public static Object unserialize(byte[] bytes) { if (bytes == null) { return null; } ByteArrayInputStream bais = null; try { bais = new ByteArrayInputStream(bytes); final ObjectInputStream ois = new ObjectInputStream(bais); return ois.readObject(); } catch (final Exception e) { throw new CacheException(e); } }}7,配置文件(此处需要Goods实体,不再赘述),配置文件中缓存可以开关,如果某个select不需要缓存,则加上 useCache="false" 属性,默认不写的话值是true
<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" ><mapper namespace="com.yjl.service.dao.GoodsDao"><cache type="com.yjl.framework.caching.mybatis.RedisCache" /><resultMap id="BaseResultMap" type="com.yjl.bean.Goods"><id column="goods_id" property="goodsId" jdbcType="INTEGER" /><result column="center_goods_id" property="centerGoodsId"jdbcType="INTEGER" /><result column="store_id" property="storeId" jdbcType="INTEGER" /><result column="brand_id" property="brandId" jdbcType="INTEGER" /></resultMap><select id="getGoodsById" resultMap="goodsDetail" parameterType="java.lang.Integer">select goods_id,center_goods_id,store_id,brand_id from goods where goods_id = #{goodsId,jdbcType=INTEGER} limit 1</select></mapper>
8,redis.properties(此处可以根据具体的namespace设置相应的缓存时间)
host=localhostport=6379connectionTimeout=5000soTimeout=4000password=database=0com.yjl.service.dao.MealDao=5com.yjl.service.dao.GoodsDao=10
代码部分已经完成,下面开始测试是否缓存
===========================华丽的分割线===========================
下面开始测试
可以看出只有第一次会查询数据库,在redis缓存时间之内不会在查询数据库
以上是本人实际工作中总结,如有错误请大家指正,欢迎大家积极评论。
1 0
- mybatis通过配置文件方式整合redis缓存,替换mybatis二级缓存
- mybatis + spring + redis(二级缓存)整合
- MyBatis--查询缓存--ehcache二级缓存配置文件详解
- 【MyBatis框架】查询缓存-二级缓存-整合ehcache
- mybatis一二级缓存详解,整合ehcache缓存,
- 【MyBatis框架】查询缓存-二级缓存-整合ehcache
- 【MyBatis框架】查询缓存-二级缓存-整合ehcache
- mybatis的二级缓存sessionFactory缓存集成redis
- mybatis的二级缓存--配置redis缓存
- mybatis整合REDIS远程缓存
- Mybatis - 查询缓存(一级缓存,二级缓存,与ehcache整合)
- MyBatis一级缓存,二级缓存
- MyBatis 一级缓存,二级缓存
- mybatis一级缓存二级缓存
- redis实现mybatis二级缓存
- mybatis redis 实现二级缓存
- mybatis+redis二级缓存
- Spring boot使用Redis集群替换mybatis二级缓存
- 进程线程及堆栈关系的总结
- asp.net中web.config配置节点大全详解
- 动态追加标签,获取某标签下的标签个数
- Android四角形状(角度)不规则ImageView方案
- LeetCode Reverse Nodes in k-Group
- mybatis通过配置文件方式整合redis缓存,替换mybatis二级缓存
- 【剑指offer】2.3.4树——面试题6:重建二叉树
- Asp.net学习笔记
- HTML5缓存机制浅析:移动端Web加载性能优化
- apache中使用mod_log_slow分析响应慢的请求
- quartz 定时器cron表达式全解析
- php中\r \r\n \t的区别示例介绍
- linux下如何获取cpu的利用率
- Linux管线命令