redis+mybatis+spring

cary_25 3年前

来自: http://canann.iteye.com/blog/2170933


redis的安装http://liuyieyer.iteye.com/blog/2078093

redis的主从高可用 http://liuyieyer.iteye.com/blog/2078095

Mybatis 的使用不多说。

Mybatis为了方便我们扩展缓存定义了一个Cache接口,看看ehcache-mybatis的源码就明白了。我们要使用自己的cache同样的实现Cache接口即可。直接上代码

public class RedisCache   implements Cache {            private static Log logger = LogFactory.getLog(RedisCache.class);            private Jedis redisClient = createClient();            /** The ReadWriteLock. */            private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();                        private String id;            public RedisCache(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 createClient() {                    try {                            JedisPool pool = new JedisPool(new JedisPoolConfig(), "172.60.0.172");                           return pool.getResource();                    } catch (Exception e) {                            e.printStackTrace();                    }                    throw new RuntimeException("初始化连接池错误");            }                                  }            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) {                    if(bytes == null)return null;                    ByteArrayInputStream bais = null;                    try {                            // 反序列化                            bais = new ByteArrayInputStream(bytes);                            ObjectInputStream ois = new ObjectInputStream(bais);                            return ois.readObject();                    } catch (Exception e) {                            e.printStackTrace();                    }                    return null;            }    }

在看ehcache-mybatis的源码 它真正使用cache的方式是通过集成org.apache.ibatis.cache.decorators.LoggingCache 这个类实现的,照猫画虎,直接我们也继承

public class LoggingRedisCache extends LoggingCache {                public LoggingRedisCache(String id) {                    super(new RedisCache(id));            }              }

在mapper.xml中添加如下cache标签

<!-- 启用缓存 -->        <cache type="cn.seafood.cache.LoggingRedisCache" />

 在mybatis的核心文件中开启缓存

<settings>        <!-- 这个配置使全局的映射器启用或禁用缓存 -->        <setting name="cacheEnabled" value="true" />     <!-- 对于未知的SQL查询,允许返回不同的结果集以达到通用的效果 -->                <setting name="multipleResultSetsEnabled" value="true"/>        <!-- 配置默认的执行器。SIMPLE 执行器没有什么特别之处。REUSE 执行器重用预处理语句。BATCH 执行器重用语句和批量更新 -->        <setting name="defaultExecutorType" value="REUSE" />        <!-- 全局启用或禁用延迟加载。当禁用时,所有关联对象都会即时加载。 -->        <setting name="lazyLoadingEnabled" value="false" />        <setting name="aggressiveLazyLoading" value="true" />        <!-- <setting name="enhancementEnabled" value="true"/> -->        <!-- 设置超时时间,它决定驱动等待一个数据库响应的时间。 -->        <setting name="defaultStatementTimeout" value="25000" />    </settings>

<setting name="lazyLoadingEnabled" value="false" />

<setting name="aggressiveLazyLoading" value="true" />

注意着两个属性,需要把属性延迟加载和关联对象加载给关闭了,不然放进redis中的cglib代理对象,在对数据发生更改的时候,会出错。

 

 

在上一篇文中的Cahe类存在各种问题如:一直使用同一个连接,每次都创建新的Cache,项目中老是爆出connection timeout 的异常,存储的key过长等等一系列的问题,解决问题最好的办法就是看源码和看官方的文档说明,jedis的文档还是够用的,接下来把cache也改造以下附上代码。

package cn.seafood.cache;        import java.io.ByteArrayInputStream;    import java.io.ByteArrayOutputStream;    import java.io.ObjectInputStream;    import java.io.ObjectOutputStream;    import java.util.concurrent.locks.ReadWriteLock;    import java.util.concurrent.locks.ReentrantReadWriteLock;        import org.apache.commons.logging.Log;    import org.apache.commons.logging.LogFactory;    import org.apache.ibatis.cache.Cache;        import redis.clients.jedis.Jedis;    import redis.clients.jedis.JedisPool;    import redis.clients.jedis.JedisPoolConfig;    import redis.clients.jedis.exceptions.JedisConnectionException;    import cn.seafood.util.PropertiesLoader;        /**    *    * @ClassName: RedisCache   * @Description: TODO(使用第三方缓存服务器redis,处理二级缓存)   * @author LiuYi   * @date 2014年6月9日 下午1:37:46   *    */    public class RedisCache   implements Cache {            private static Log log = LogFactory.getLog(RedisCache.class);            /** The ReadWriteLock. */            private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();                        private String id;            public RedisCache(final String id) {                    if (id == null) {                            throw new IllegalArgumentException("必须传入ID");                    }                    log.debug("MybatisRedisCache:id=" + id);                    this.id=id;            }                        @Override            public String getId() {                    return this.id;            }                @Override            public int getSize() {                    Jedis jedis = null;                    JedisPool jedisPool = null;                    int result = 0;                    boolean borrowOrOprSuccess = true;                    try {                            jedis   = CachePool.getInstance().getJedis();                            jedisPool = CachePool.getInstance().getJedisPool();                            result = Integer.valueOf(jedis.dbSize().toString());                    } catch (JedisConnectionException e) {                            borrowOrOprSuccess = false;                            if (jedis != null)                                    jedisPool.returnBrokenResource(jedis);                    } finally {                            if (borrowOrOprSuccess)                                    jedisPool.returnResource(jedis);                    }                    return result;                                 }                @Override            public void putObject(Object key, Object value) {                    if(log.isDebugEnabled())                    log.debug("putObject:" + key.hashCode() + "=" + value);                    if(log.isInfoEnabled())                    log.info("put to redis sql :" +key.toString());                    Jedis jedis = null;                    JedisPool jedisPool = null;                    boolean borrowOrOprSuccess = true;                    try {                            jedis   = CachePool.getInstance().getJedis();                            jedisPool = CachePool.getInstance().getJedisPool();                            jedis.set(SerializeUtil.serialize(key.hashCode()), SerializeUtil.serialize(value));                    } catch (JedisConnectionException e) {                            borrowOrOprSuccess = false;                            if (jedis != null)                                    jedisPool.returnBrokenResource(jedis);                    } finally {                            if (borrowOrOprSuccess)                                    jedisPool.returnResource(jedis);                    }                                }                @Override            public Object getObject(Object key) {                    Jedis jedis = null;                    JedisPool jedisPool = null;                    Object value = null;                    boolean borrowOrOprSuccess = true;                    try {                            jedis   = CachePool.getInstance().getJedis();                            jedisPool = CachePool.getInstance().getJedisPool();                            value  = SerializeUtil.unserialize(jedis.get(SerializeUtil.serialize(key.hashCode())));                    } catch (JedisConnectionException e) {                            borrowOrOprSuccess = false;                            if (jedis != null)                                    jedisPool.returnBrokenResource(jedis);                    } finally {                            if (borrowOrOprSuccess)                                    jedisPool.returnResource(jedis);                    }                    if(log.isDebugEnabled())                    log.debug("getObject:" + key.hashCode() + "=" + value);                    return value;            }                @Override            public Object removeObject(Object key) {                    Jedis jedis = null;                    JedisPool jedisPool = null;                    Object value = null;                    boolean borrowOrOprSuccess = true;                    try {                            jedis   = CachePool.getInstance().getJedis();                            jedisPool = CachePool.getInstance().getJedisPool();                            value  = jedis.expire(SerializeUtil.serialize(key.hashCode()), 0);                    } catch (JedisConnectionException e) {                            borrowOrOprSuccess = false;                            if (jedis != null)                                    jedisPool.returnBrokenResource(jedis);                    } finally {                            if (borrowOrOprSuccess)                                    jedisPool.returnResource(jedis);                    }                    if(log.isDebugEnabled())                    log.debug("getObject:" + key.hashCode() + "=" + value);                    return value;            }                @Override            public void clear() {                    Jedis jedis = null;                    JedisPool jedisPool = null;                    boolean borrowOrOprSuccess = true;                    try {                            jedis   = CachePool.getInstance().getJedis();                            jedisPool = CachePool.getInstance().getJedisPool();                            jedis.flushDB();                            jedis.flushAll();                    } catch (JedisConnectionException e) {                            borrowOrOprSuccess = false;                            if (jedis != null)                                    jedisPool.returnBrokenResource(jedis);                    } finally {                            if (borrowOrOprSuccess)                                    jedisPool.returnResource(jedis);                    }            }                @Override            public ReadWriteLock getReadWriteLock() {                    return readWriteLock;            }           /**           *           * @ClassName: CachePool          * @Description: TODO(单例Cache池)          * @author LiuYi          * @date 2014年6月17日 上午10:50:52          *           */            public static class CachePool {                    JedisPool pool;                    private static final CachePool cachePool = new CachePool();                                        public static CachePool getInstance(){                            return cachePool;                    }                    private CachePool() {                            JedisPoolConfig config = new JedisPoolConfig();                            config.setMaxIdle(100);                            config.setMaxWaitMillis(1000l);                             PropertiesLoader pl =  new PropertiesLoader("classpath:config/redis.properties");                             pool = new JedisPool(config,pl.getProperty("redisvip"));                    }                    public  Jedis getJedis(){                            Jedis jedis = null;                            boolean borrowOrOprSuccess = true;                            try {                                    jedis = pool.getResource();                            } catch (JedisConnectionException e) {                                    borrowOrOprSuccess = false;                                    if (jedis != null)                                            pool.returnBrokenResource(jedis);                            } finally {                                    if (borrowOrOprSuccess)                                            pool.returnResource(jedis);                            }                            jedis = pool.getResource();                            return jedis;                    }                                        public JedisPool getJedisPool(){                            return this.pool;                    }                                }                                    public static 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) {                            if(bytes == null)return null;                            ByteArrayInputStream bais = null;                            try {                                    // 反序列化                                    bais = new ByteArrayInputStream(bytes);                                    ObjectInputStream ois = new ObjectInputStream(bais);                                    return ois.readObject();                            } catch (Exception e) {                                    e.printStackTrace();                            }                            return null;                    }            }    }

 参考链接:http://liuyieyer.iteye.com/blog/2081382