mybatis-自定义缓存-redis二级缓存
在mybatis一级缓存二级缓存中已经介绍过了二级缓存的大致原理。下面我们用redis来实现一下二级缓存。环境是springmvc+mybatis+redis
步骤一、引入redis相关的maven依赖
<!-- spring-redis实现 --> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-redis</artifactId> <version>1.6.2.RELEASE</version> </dependency> <!-- redis客户端jar --> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.8.0</version> </dependency>
步骤二、新建redis的配置redis.xml,redis.properties
<?xml version="1.0" encoding="utf-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd" default-autowire="byName" default-lazy-init="false"> <!--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连接池管理工厂--> <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" p:hostName="${redis.host}" p:port="${redis.port}" p:password="${redis.pass}" p:poolConfig-ref="poolConfig"/> <!-- 使用中间类解决RedisCache.jedisConnectionFactory的静态注入,从而使MyBatis实现第三方缓存 --> <bean id="redisCacheTransfer" class="com.yihaomen.mybatis.cache.RedisCacheTransfer"> <property name="jedisConnectionFactory" ref="jedisConnectionFactory"/> </bean> </beans>
redis.host=192.168.31.55 redis.port=6379 redis.pass= redis.maxIdle=300 redis.maxActive=600 redis.maxWait=1000 redis.testOnBorrow=true
步骤三、将redis.xml引入到spring的配置文件applicationContext.xml
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations"> <list> <value>classpath*:jdbc.properties</value> <value>classpath*:redis.properties</value> </list> </property> </bean> <import resource="redis.xml"/>
步骤四、创建缓存实现类RedisCache
package com.yihaomen.mybatis.cache; import org.apache.ibatis.cache.Cache; 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; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; /** * * @ProjectName: springmvc-mybatis * @Description: 使用第三方内存数据库Redis作为二级缓存 * @author: lisen * @date: 2017/11/8 */ public class RedisCache implements Cache{ private static JedisConnectionFactory jedisConnectionFactory; private final String id; private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); public RedisCache(final String id) { if(id == null) { throw new IllegalArgumentException("Cache instances require an ID"); } this.id = id; } public static void setJedisConnectionFactory(JedisConnectionFactory jedisConnectionFactory) { RedisCache.jedisConnectionFactory = jedisConnectionFactory; } @Override public String getId() { return this.id; } public void putObject(Object key, Object value) { JedisConnection connection = null; try { connection = jedisConnectionFactory.getConnection(); RedisSerializer<Object> serializer = new JdkSerializationRedisSerializer(); connection.set(serializer.serialize(key), serializer.serialize(value)); } catch (JedisConnectionException e) { e.printStackTrace(); } finally { if(connection != null) { connection.close(); } } } public Object getObject(Object key) { Object result = null; JedisConnection connection = null; try { connection = jedisConnectionFactory.getConnection(); RedisSerializer<Object> serializer = new JdkSerializationRedisSerializer(); result = serializer.deserialize(connection.get(serializer.serialize(key))); } catch (JedisConnectionException e) { e.printStackTrace(); } finally { if(connection != null) { connection.close(); } } return result; } 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; } @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(); } } } 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; } public ReadWriteLock getReadWriteLock() { return this.readWriteLock; } }
步骤五、 创建中间类RedisCacheTransfer,完成RedisCache.jedisConnectionFactory的静态注入
package com.yihaomen.mybatis.cache; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; /** * * @ProjectName: springmvc-mybatis * @Description: 创建中间类RedisCacheTransfer,完成RedisCache.jedisConnectionFactory的静态注入, * 静态注入中间类 * @author: lisen * @date: 2017/11/8 */ public class RedisCacheTransfer { @Autowired public void setJedisConnectionFactory(JedisConnectionFactory jedisConnectionFactory) { RedisCache.setJedisConnectionFactory(jedisConnectionFactory); } }
步骤六、在mapper(User.xml)中加入MyBatis二级缓存
<?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.yihaomen.mybatis.dao.UserMapper"> <cache type="com.yihaomen.mybatis.cache.RedisCache"/>
<select id="selectUserByID" parameterType="int" resultType="User" >
select * from `user` where id = #{id}
</select>
</mapper>
我们还可以配置在SQL层面上的缓存配置,来决定它们是否需要使用或者刷新缓存,我们往往根据两个属性:userCache和flushCache来完成,其中userCache表示是否需要使用缓存,儿flushCache表示插入后是否需要刷新缓存,比如
<select ... flushCache="false" useCache="true"/>
<insert ... flushCache="true"/>
<update... flushCache="true"/>
<delete... flushCache="true"/>
步骤七、在mybatis-config.xml文件中开启二级缓存
<settings> <!--这个配置使全局的映射器(二级缓存)启用或禁用缓存--> <setting name="cacheEnabled" value="true" /> </setting>
步骤八、单元测试
package com.yihaomen.service.test; import com.yihaomen.mybatis.dao.UserMapper; import com.yihaomen.mybatis.model.User; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import java.util.List; /** * * @ProjectName: springmvc-mybatis * @Description: * @author: lisen * @date: 2017/11/9 */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration({"classpath:applicationContext.xml"}) public class UserSpringTest { @Autowired private UserMapper userMapper; @Test public void selectUserById() { List<User> users = userMapper.selectUserById(11L); } }
https://gitee.com/huayicompany/springmvc-mybatis
参考:
[1]博客,http://blog.csdn.net/xiadi934/article/details/50786293