改用第三方redis作为二级缓存 ,缓存取值顺序,二级缓存 --->一级缓存 ---> 数据库查询
核心 配置类
#mybatis
#entity扫描的包名
mybatis.type-aliases-package=com.xiaolyuh.domain.model
#Mapper.xml所在的位置
mybatis.mapper-locations=classpath*:/mybaits/*Mapper.xml
#开启MyBatis的二级缓存
mybatis.configuration.cache-enabled=true
#pagehelper
pagehelper.helperDialect=mysql
pagehelper.reasonable=true
pagehelper.supportMethodsArguments=true
pagehelper.params=count=countSql
POM的依赖文件
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-ehcache</artifactId>
<version>1.0.0</version>
</dependency>
自定的Mybatis缓存
核心 配置类,定义缓存后,需要更新和删除的策略,删除redis 缓存数据,
import com.xiaolyuh.holder.SpringContextHolder;
import org.apache.ibatis.cache.Cache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.CollectionUtils;
import java.util.Collections;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* 使用Redis来做Mybatis的二级缓存
* 实现Mybatis的Cache接口
*/
public class MybatisRedisCache implements Cache {
private static final Logger logger = LoggerFactory.getLogger(MybatisRedisCache.class);
// 读写锁
private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(true);
private RedisTemplate<String, Object> redisTemplate = SpringContextHolder.getBean("redisTemplate");
private String id;
public MybatisRedisCache(final String id) {
if (id == null) {
throw new IllegalArgumentException("Cache instances require an ID");
}
logger.info("Redis Cache id " + id);
this.id = id;
}
@Override
public String getId() {
return this.id;
}
@Override
public void putObject(Object key, Object value) {
if (value != null) {
// 向Redis中添加数据,有效时间是2天
redisTemplate.opsForValue().set(key.toString(), value, 2, TimeUnit.DAYS);
}
}
@Override
public Object getObject(Object key) {
try {
if (key != null) {
Object obj = redisTemplate.opsForValue().get(key.toString());
return obj;
}
} catch (Exception e) {
logger.error("redis ");
}
return null;
}
@Override
public Object removeObject(Object key) {
try {
if (key != null) {
redisTemplate.delete(key.toString());
}
} catch (Exception e) {
}
return null;
}
@Override
public void clear() {
logger.debug("清空缓存");
try {
Set<String> keys = redisTemplate.keys("*:" + this.id + "*");
if (!CollectionUtils.isEmpty(keys)) {
redisTemplate.delete(keys);
}
} catch (Exception e) {
}
}
@Override
public int getSize() {
Long size = (Long) redisTemplate.execute(new RedisCallback<Long>() {
@Override
public Long doInRedis(RedisConnection connection) throws DataAccessException {
return connection.dbSize();
}
});
return size.intValue();
}
@Override
public ReadWriteLock getReadWriteLock() {
return this.readWriteLock;
}
}
Mapper文件
把上面重写的cache接口类,配置在每个mapper文件里,作为缓存参数 参数有过期算法,过期时间,内存大小等
<cache type="com.xiaolyuh.cache.MybatisRedisCache">
<?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.xiaolyuh.domain.mapper.PersonMapper">
<cache type="com.xiaolyuh.cache.MybatisRedisCache">
<property name="eviction" value="LRU" />
<property name="flushInterval" value="6000000" />
<property name="size" value="1024" />
<property name="readOnly" value="false" />
</cache>
<resultMap id="BaseResultMap" type="com.xiaolyuh.domain.model.Person">
<!--
WARNING - @mbggenerated
This element is automatically generated by MyBatis Generator, do not modify.
-->
<id column="id" property="id" jdbcType="BIGINT"/>
<result column="name" property="name" jdbcType="VARCHAR"/>
<result column="age" property="age" jdbcType="INTEGER"/>
<result column="address" property="address" jdbcType="VARCHAR"/>
</resultMap>
<sql id="Base_Column_List">
id, name, age, address
</sql>
<select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Long">
<!--
WARNING - @mbggenerated
This element is automatically generated by MyBatis Generator, do not modify.
-->
select
<include refid="Base_Column_List"/>
from person
where id = #{id,jdbcType=BIGINT}
</select>
<delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
<!--
WARNING - @mbggenerated
This element is automatically generated by MyBatis Generator, do not modify.
-->
delete from person
where id = #{id,jdbcType=BIGINT}
</delete>
<insert id="insertSelective" parameterType="com.xiaolyuh.domain.model.Person">
<selectKey resultType="java.lang.Long" keyProperty="id" order="AFTER">
SELECT LAST_INSERT_ID()
</selectKey>
insert into person
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="name != null">
name,
</if>
<if test="age != null">
age,
</if>
<if test="address != null">
address,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="name != null">
#{name,jdbcType=VARCHAR},
</if>
<if test="age != null">
#{age,jdbcType=INTEGER},
</if>
<if test="address != null">
#{address,jdbcType=VARCHAR},
</if>
</trim>
</insert>
<update id="updateByPrimaryKeySelective" parameterType="com.xiaolyuh.domain.model.Person">
update person
<set>
<if test="name != null">
name = #{name,jdbcType=VARCHAR},
</if>
<if test="age != null">
age = #{age,jdbcType=INTEGER},
</if>
<if test="address != null">
address = #{address,jdbcType=VARCHAR},
</if>
</set>
where id = #{id,jdbcType=BIGINT}
</update>
<!-- 对这个语句useCache="true"默认是true,可以不写 -->
<select id="findAll" resultMap="BaseResultMap" useCache="true">
select
<include refid="Base_Column_List"/>
from person
</select>
<!-- 对这个语句禁用二级缓存 -->
<select id="findByPage" resultMap="BaseResultMap" useCache="false">
select
<include refid="Base_Column_List"/>
from person
</select>
</mapper>