Spring+Mybatis+redis

使用redis作为mybatis的二级缓存

需要的jar包 需要特别说明的是 我一套jar包也是经历过实际检验的 网上很多的教程里面的包组合根本是是用不了的 无非就是版本不搭配

除了Spring必须的jar包以外 (Spring是4X)




需要jar包的可以去这个网址:http://mvnrepository.com/

这几个jar包的组合是可以用的 看网上教程提供的jar包组合太恐怖了。各种搭配失败 而且劝大家选择jar包的时候 不要一味追求高版本 要选最稳定得

好 真正开始配置缓存

首先你需要有一个redis数据库。建议是linux下的redis 要是非要使用Windows的也可以 github上有大神已经做出来了 具体的安装教程网上太多了 很幸运 都是可以用的。。

然后 你需要构建一个redis的类为了序列化需要缓存的东西到redis数据库中

package main.java.com.hdd.core.util;

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 org.springframework.data.redis.connection.jedis.JedisConnection;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;

import redis.clients.jedis.exceptions.JedisConnectionException;


public class RedisCache implements Cache //实现类
{
    private static final Logger logger = LoggerFactory.getLogger(RedisCache.class);

    private static JedisConnectionFactory jedisConnectionFactory;

    private final String id;

    /**
     * The {@code ReadWriteLock}.
     */
    private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();

    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 void clear()
    {
        JedisConnection connection = null;
        try
        {
            connection = jedisConnectionFactory.getConnection(); //连接清除数据
            connection.flushDb();
            connection.flushAll();
        }
        catch (JedisConnectionException e)
        {
            e.printStackTrace();
        }
        finally
        {
            if (connection != null) {
                connection.close();
            }
        }
    }

    @Override
    public String getId()
    {
        return this.id;
    }

    @Override
    public Object getObject(Object key)
    {
        Object result = null;
        JedisConnection connection = null;
        try
        {
            connection = jedisConnectionFactory.getConnection();
            RedisSerializer<Object> serializer = new JdkSerializationRedisSerializer(); //借用spring_data_redis.jar中的JdkSerializationRedisSerializer.class
            result = serializer.deserialize(connection.get(serializer.serialize(key))); //利用其反序列化方法获取值
        }
        catch (JedisConnectionException e)
        {
            e.printStackTrace();
        }
        finally
        {
            if (connection != null) {
                connection.close();
            }
        }
        return result;
    }

    @Override
    public ReadWriteLock getReadWriteLock()
    {
        return this.readWriteLock;
    }

    @Override
    public int getSize()
    {
        int result = 0;
        JedisConnection connection = null;
        try
        {
            connection = jedisConnectionFactory.getConnection();
            result = Integer.valueOf(connection.dbSize().toString());
        }
        catch (JedisConnectionException e)
        {
            e.printStackTrace();
        }
        finally
        {
            if (connection != null) {
                connection.close();
            }
        }
        return result;
    }

    @Override
    public void putObject(Object key, Object value)
    {
        JedisConnection connection = null;
        try
        {
            logger.info(">>>>>>>>>>>>>>>>>>>>>>>>putObject:"+key+"="+value);
            connection = jedisConnectionFactory.getConnection();
            RedisSerializer<Object> serializer = new JdkSerializationRedisSerializer(); //借用spring_data_redis.jar中的JdkSerializationRedisSerializer.class
            connection.set(serializer.serialize(key), serializer.serialize(value)); //利用其序列化方法将数据写入redis服务的缓存中

        }
        catch (JedisConnectionException e)
        {
            e.printStackTrace();
        }
        finally
        {
            if (connection != null) {
                connection.close();
            }
        }
    }

    @Override
    public Object removeObject(Object key)
    {
        JedisConnection connection = null;
        Object result = null;
        try
        {
            connection = jedisConnectionFactory.getConnection();
            RedisSerializer<Object> serializer = new JdkSerializationRedisSerializer();
            result =connection.expire(serializer.serialize(key), 0);
        }
        catch (JedisConnectionException e)
        {
            e.printStackTrace();
        }
        finally
        {
            if (connection != null) {
                connection.close();
            }
        }
        return result;
    }

    public static void setJedisConnectionFactory(JedisConnectionFactory jedisConnectionFactory) {
        RedisCache.jedisConnectionFactory = jedisConnectionFactory;
    }

}
特意贴出了导入的包 希望看清楚 别import错了

然后再来一个

package main.java.com.hdd.core.util;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;

public class RedisCacheTransfer {


        @Autowired
        public void setJedisConnectionFactory(JedisConnectionFactory jedisConnectionFactory) {
        RedisCache.setJedisConnectionFactory(jedisConnectionFactory);
    }


}


再然后 Spring里面的配置 :


<context:property-placeholder location="classpath:main/resources/redis.properties" />
<!-- redis数据源 -->
<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
    <property name="maxIdle" value="${redis.maxIdle}" />
    <property name="maxTotal" value="${redis.maxActive}" />
    <property name="maxWaitMillis" value="${redis.maxWait}" />
    <property name="testOnBorrow" value="${redis.testOnBorrow}"/>
</bean>
<!-- Spring-redis连接池管理工厂 -->
<context:property-placeholder location="classpath:main/resources/redis.properties" />
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
      p:host-name="${redis.host}" p:port="${redis.port}" p:password="${redis.pass}"  p:pool-config-ref="poolConfig"/>
<!-- 使用中间类解决RedisCache.jedisConnectionFactory的静态注入,从而使MyBatis实现第三方缓存 -->
<bean id="redisCacheTransfer" class="main.java.com.hdd.core.util.RedisCacheTransfer">
    <property name="jedisConnectionFactory" ref="jedisConnectionFactory"/>
</bean>
这个redis的连接池的配置 只在jedis2.4以下的版本有 具体多往下我也没研究过 如果是高版本 那么数据源那里就会有错 

然后提一句 如果你已经配了jdbc的配置文件  那么需要在Spring里面这样:

<bean id="configProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
    <property name="locations">
        <list>
            <value>classpath:main/resources/jdbc.properties</value>
            <value>classpath:main/resources/redis.properties</value>
        </list>
    </property>
    <property name="fileEncoding" value="UTF-8"/>
</bean>
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer">
    <property name="properties" ref="configProperties"/>
</bean>
做一个list的配置 

然后redis的配置:

redis.host=127.0.0.1
redis.port=6379
redis.pass=

redis.maxIdle=300
redis.maxActive=600
redis.maxWait=1000
redis.testOnBorrow=true
然后都配好了之后 需要在Mybatis的配置中开启缓存 很重要

<!-- 全局映射器启用缓存 -->
<setting name="cacheEnabled" value="true" />
然后 准备工作算是完成了 

接下来去mapper中开启redis

<cache type="main.java.com.hdd.core.util.RedisCache"/>
这个是需要你每个要使用缓存的mapper中都要开启的

然后再具体在sql语句上:

<select id="getXs" resultType="main.java.com.hdd.tree.entity.Xs" useCache="true">
useCache 开启 如果不使用就 改为false

很容易被忘记的一点是 现在 我们还需要去实体里面开启序列化 就是你绑定的实体到mybatis的那个实体里 

public class Xk implements Serializable
这样才是真正的成功了

然后我们实验一下 :


这个就是缓存命中了  第一次运行是不会命中的 我这个已经是很多次了 运行的时间大概是1.3秒 如果关闭了缓存就是7.3秒左右 提升还是很大的 

然后我们看一下redis里面发生了什么变化 



获取key后会出现很多奇怪的东西 但是细细看 会发现里面有sql语句 这就已经将sql执行的东西放进了redis里面 只要你不设置key的过期时间 这些key就会一直在 

ok 大功告成


最终说明: 如果在mapper.xml中使用了cache标签 会默认开启这个mapper.xml下面所有的select标签使用的sql的缓存 如果不需要的话 需要手动调整为usecache=false 所以其实usecache=true是默认开启的 写不写都可以 但是不用的时候一定要给不用的方法 加上usecache=false 

而且 这样的缓存数据是不会自动检测你的数据是否发生了变化 也就是说 如果你更新了数据库的数据 那么再查的时候 一定还是用的缓存 现在的解决办法没有特别好的指定更新 只能flush redis 就是在你update delete insert这种操作的mapper里面(当然是开启了缓存的查询) 加上flushCache = true 这样每次更新了数据库的时候 redis就会刷新 以前的key就没有了 这样能够保证redis的数据同步 但是同步是有时间的 不知道在高并发的时候会不会有时间差 所以最好深入研究redis 看看各种过期策略。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值