Mybatsi默认缓存对象 PerpetualCache,是本地缓存 。
将缓存数据存入redis操作过程:
package com.vince.MyBatisCache;
import org.apache.ibatis.cache.Cache;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.context.ContextLoader;
import java.util.Set;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class MyMyBatisCache implements Cache {
private String id; // 当前mapper的 namespace
private final ReadWriteLock lock = new ReentrantReadWriteLock();
RedisTemplate<String,Object> template;
public MyMyBatisCache(){} //无参构造
public MyMyBatisCache(String id){ // mybatis 创建缓存组件实例时传入
System.out.println("缓存id:"+id);
this.id=id;
}
@Override
public String getId() {
return this.id;
}
// 缓存数据
@Override
public void putObject(Object key, Object value) {
template.opsForValue().set(key.toString(), value);// 将查询结果存入 redis 缓存后备用
}
// 检查缓存
@Override
public Object getObject(Object key) {
// 获取redis组件
template =(RedisTemplate) ContextLoader.getCurrentWebApplicationContext().getBean("redisTemplate");
System.out.println("检查缓存 key:"+key.getClass());
Object cache = template.opsForValue().get(key.toString()); // 通过sql语句检查是否有缓存可用
if (cache!=null){
System.out.println("命中缓存~");
return cache;
}else{
System.out.println("检查缓存 但是没有缓存数据~");
return null;
}
}
//删除某一个缓存数据
@Override
public Object removeObject(Object key) {
template = (RedisTemplate) ContextLoader.getCurrentWebApplicationContext().getBean("redisTemplate");
template.delete(key.toString() );
return null;
}
// 当一个mapper中触发了一个写操作之后 清空所有缓存数据
@Override
public void clear() {
System.out.println("nameSpace:"+this.getId()+"发生了写操作,清空了所有缓存数据~");
template = (RedisTemplate) ContextLoader.getCurrentWebApplicationContext().getBean("redisTemplate");
// 获取当前mapper下的所有缓存 key
Set<String> keys = template.keys("*" + this.getId() + "*");
// 删除 keys
template.delete(keys);
}
@Override
public int getSize() {
return 0;
}
@Override
public ReadWriteLock getReadWriteLock() {
return this.lock;
}
}
<?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">
<!-- namespace:命名空间,用于隔离sql -->
<!-- 还有一个很重要的作用,使用动态代理开发DAO. namespace必须和Mapper接口类路径一致 -->
<mapper namespace="com.vince.dao.UserDao">
<cache type="com.vince.MyBatisCache.MyMyBatisCache"></cache> // 使用自定义缓存组件
<!--查寻所有-->
<select id="selectAll" resultType="User">
SELECT * FROM t_user
</select>
</mapper>
Redis 配置文件:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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">
<!-- 连接池配置 -->
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<!-- 最多空闲连接数 -->
<property name="maxIdle" value="1" />
<!-- 最多有多少连接 -->
<property name="maxTotal" value="5" />
<property name="minIdle" value="1"></property>
<!-- 连接数用完时,是否阻塞,阻塞超过maxWaitMillis会抛出异常 -->
<property name="blockWhenExhausted" value="true" />
<!-- 检出连接时,最大等待时长 -->
<property name="maxWaitMillis" value="30000" />
<!-- 在检出时是否检测 -->
<property name="testOnBorrow" value="false" />
<!-- 空闲时是否检测连接是否可用 -->
<property name="testWhileIdle" value="false"></property>
<!-- Evict=驱逐 连接至少要空闲多少时间才会成为可以被驱逐线程扫描并移除 -->
<property name="minEvictableIdleTimeMillis" value="60000"></property>
<!-- 驱逐线程 两次驱逐之间要sleep的时间 如果小于0,则不会有驱逐线程,则minEvictableIdleTimeMillis无效-->
<property name="timeBetweenEvictionRunsMillis" value="30000"></property>
<!-- 驱逐线程每次最多扫描几个连接 -->
<property name="numTestsPerEvictionRun" value="3"></property>
<!-- last in first out 检出策略 后入先出 或 先入先出 -->
<property name="lifo" value="true"></property>
</bean>
<!-- 连接Factory -->
<bean id="jedisConnectionFactory"
class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<!-- Redis主机 -->
<property name="hostName" value="192.168.11.128"></property>
<property name="port" value="8000"></property>
<!-- 连接池配置信息 -->
<property name="poolConfig" ref="jedisPoolConfig"></property>
</bean>
<!-- 如果没有设置序列化,则默认使用DefaultSerializer。
声明序列化组件
-->
<bean id="ss" class="org.springframework.data.redis.serializer.StringRedisSerializer" />
<bean class="org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer" id="jacks" />
<bean class="com.alibaba.fastjson.support.spring.GenericFastJsonRedisSerializer" id="fast"></bean>
<!-- RedisTemplate:核心组件 -->
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"
p:connectionFactory-ref="jedisConnectionFactory"
p:keySerializer-ref="ss"
p:hashKeySerializer-ref="ss"
p:hashValueSerializer-ref="fast"
p:stringSerializer-ref="ss"
p:valueSerializer-ref="fast"></bean>
</beans>
在Spring 工厂中导入 redis 配置文件:
<!--导入redis--> <import resource="classpath:applicationContext-redsi.xml"></import>