在MyBatis中,默认的二级缓存Cache实现是PerpetualCache,而通常,这种方式满足不了分布式集群的项目,这时候,五门可以借助一些第三方服务来做缓存,比如Redis,下面,来尝试下用Redis做MyBatis的二级缓存
开启二级缓存
实现自己的cache
package top.yuyufeng.learn.mybatis.cache;
import org.apache.ibatis.cache.Cache;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* @author yuyufeng
* @date 2018/6/25.
*/
public class RedisCache implements Cache {
private final String id;
private static ValueOperations<String, Object> valueOs;
private static RedisTemplate<String, String> template;
public static void setValueOs(ValueOperations<String, Object> valueOs) {
RedisCache.valueOs = valueOs;
}
public static void setTemplate(RedisTemplate<String, String> template) {
RedisCache.template = template;
}
private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
public RedisCache(String id) {
if (id == null) {
throw new IllegalArgumentException("Cache instances require an ID");
}
this.id = id;
}
@Override
public String getId() {
return this.id;
}
@Override
public void putObject(Object key, Object value) {
valueOs.set(key.toString(), value, 10, TimeUnit.MINUTES);
}
@Override
public Object getObject(Object key) {
return valueOs.get(key.toString());
}
@Override
public Object removeObject(Object key) {
valueOs.set(key.toString(), "", 0, TimeUnit.MINUTES);
return key;
}
@Override
public void clear() {
template.getConnectionFactory().getConnection().flushDb();
}
@Override
public int getSize() {
return template.getConnectionFactory().getConnection().dbSize().intValue();
}
@Override
public ReadWriteLock getReadWriteLock() {
return this.readWriteLock;
}
}
这里使用到了Spring-data-redis
mapper文件中使用自定义的cache
<cache type="top.yuyufeng.learn.mybatis.cache.RedisCache"/>
调试
package top.yuyufeng.learn.mybatis.service;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import top.yuyufeng.learn.mybatis.cache.RedisCache;
import top.yuyufeng.learn.mybatis.entity.Blog;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* @author yuyufeng
* @date 2018/6/13.
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:spring/spring-redis.xml","classpath:spring/spring-service.xml"})
public class CacheTest {
@Resource(name="redisTemplate")
private ValueOperations<String, Object> valueOs;
@Autowired
private RedisTemplate<String, String> template;
@Autowired
private BlogService blogService;
@Before
public void testBefore(){
RedisCache.setTemplate(this.template);
RedisCache.setValueOs(this.valueOs);
}
@Test
public void selectAll() throws Exception {
List<Blog> list = blogService.selectAll();
for (Blog blog : list) {
System.out.println(blog);
}
List<Blog> list2 = blogService.selectAll();
for (Blog blog : list2) {
System.out.println(blog);
}
}
}
>
…
Cache Hit Ratio [top.yuyufeng.learn.mybatis.mapper.BlogMapper]: 0.5
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@16073fa8]
Blog{blogId=1, blogTitle=’什么是mybatis’, blogContent=’MyBatis是支持定制化SQL、存储过程以及高级映射的优秀的持久层框架。
‘, createTime=Fri May 25 14:28:35 CST 2018}
…
可以看到,我查询了两次,命中率为0.5,缓存已经生效了