Mybatis使用Redis二级缓存
在Mybatis中允许开发者自定义自己的缓存,本文将使用Redis作为Mybatis的二级缓存。在Mybatis中定义二级缓存,需要如下配置:
1、 MyBatis支持二级缓存的总开关:全局配置变量参数“cacheEnabled=true”
2、select语句所在的Mapper需配置了<cache> 或<cached-ref>节点
3、select语句的参数 useCache=true
Mybatis配置文件如下:
<settings>
<!-- 这个配置使全局的映射器启用或禁用缓存 -->
<setting name="cacheEnabled" value="true" />
<!-- 对于未知的SQL查询,允许返回不同的结果集以达到通用的效果 -->
<setting name="multipleResultSetsEnabled" value="true"/>
<!-- 配置默认的执行器。SIMPLE 执行器没有什么特别之处。REUSE 执行器重用预处理语句。BATCH 执行器重用语句和批量更新 -->
<setting name="defaultExecutorType" value="REUSE" />
<!-- 全局启用或禁用延迟加载。当禁用时,所有关联对象都会即时加载。 -->
<setting name="lazyLoadingEnabled" value="false" />
<setting name="aggressiveLazyLoading" value="true" />
<!-- <setting name="enhancementEnabled" value="true"/> -->
<!-- 设置超时时间,它决定驱动等待一个数据库响应的时间。 -->
<setting name="defaultStatementTimeout" value="25000" />
</settings>
Mybatis的Mapper的配置文件如下:
<?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="user"> <!-- 二级缓存 -->
<cache type="com.qunar.mobile.mybatis.cache.QRedisCache"/> <select id="getUsers" resultType="User" useCache="true">
select
user_id as userId, user_name as username, user_desc as userDesc, create_time as createTime
from bisystem_user
</select> </mapper>
自定义二级缓存需要实现Mybatis的Cache接口,Redis缓存实现如下:
public class QRedisCache implements Cache {
private String cacheId;
private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(true);
public QRedisCache(String cacheId) {
if (cacheId == null) {
throw new IllegalArgumentException("Cache instances require an ID");
}
this.cacheId = cacheId;
}
@Override
public String getId() {
return cacheId;
}
@Override
public void putObject(Object key, Object value) {
JedisUtils.put(key, value);
}
@Override
public Object getObject(Object key) {
return JedisUtils.get(key);
}
@Override
public Object removeObject(Object key) {
return JedisUtils.remove(key);
}
@Override
public void clear() {
JedisUtils.removeAll();
}
@Override
public int getSize() {
return 0;
}
@Override
public ReadWriteLock getReadWriteLock() {
return readWriteLock;
}
}
在QRedisCache使用的辅助类JedisUtils及SerializeUtils实现如下:
public class JedisUtils {
private static final Logger logger = Logger.getLogger(JedisUtils.class);
private static JedisPool JEDISPOOL;
static {
Properties props = new Properties();
try {
props.load(JedisUtils.class.getResourceAsStream("/redis.properties"));
JedisPoolConfig conf = new JedisPoolConfig();
conf.setMaxIdle(Integer.valueOf(props.getProperty("jedis.pool.maxIdle")));
conf.setTestOnBorrow(Boolean.valueOf(props.getProperty("jedis.pool.testOnBorrow")));
conf.setTestOnReturn(Boolean.valueOf(props.getProperty("jedis.pool.testOnReturn")));
JEDISPOOL = new JedisPool(conf, props.getProperty("redis.ip"), Integer.valueOf(props.getProperty("redis.port")));
} catch (IOException e) {
logger.error("加载[jedis.properties]异常[" + e.getMessage() + "]", e);
}
}
public static Jedis getJedis() {
return JEDISPOOL.getResource();
}
public static void recycleJedis(Jedis jedis) {
jedis.close();
}
/**
* Redis存储Object序列化流
* */
public static void put(Object key, Object value) {
Jedis jedis = getJedis();
jedis.set(SerializeUtils.serialize(key), SerializeUtils.serialize(value));
recycleJedis(jedis);
}
public static <T> T get(Object key) {
Jedis jedis = getJedis();
T value = SerializeUtils.unserialize(jedis.get(SerializeUtils.serialize(key)));
recycleJedis(jedis);
return value;
}
public static Long remove(Object key) {
Jedis jedis = getJedis();
Long num = jedis.del(SerializeUtils.serialize(key));
recycleJedis(jedis);
return num;
}
public static void removeAll() {
Jedis jedis = getJedis();
jedis.flushDB();
recycleJedis(jedis);
}
}
public class SerializeUtils {
private static final Logger logger = Logger.getLogger(SerializeUtils.class);
private static void close(ObjectOutputStream objectOutputStream, ByteArrayOutputStream byteArrayOutputStream) {
try {
if (byteArrayOutputStream != null) {
byteArrayOutputStream.close();
}
if (objectOutputStream != null) {
objectOutputStream.close();
}
} catch (Exception e) {
e.printStackTrace();
logger.error("关闭IO资源异常[" + e.getMessage() + "]", e);
}
}
private static void close(ObjectInputStream objectInputStream, ByteArrayInputStream byteArrayInputStream) {
try {
if (objectInputStream != null) {
objectInputStream.close();
}
if (byteArrayInputStream != null) {
byteArrayInputStream.close();
}
} catch (Exception e) {
e.printStackTrace();
logger.error("关闭IO资源异常[" + e.getMessage() + "]", e);
}
}
public static byte[] serialize(Object object) {
ObjectOutputStream objectOutputStream = null;
ByteArrayOutputStream byteArrayOutputStream = null;
try {
byteArrayOutputStream = new ByteArrayOutputStream();
objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
objectOutputStream.writeObject(object);
byte[] bytes = byteArrayOutputStream.toByteArray();
return bytes;
} catch (Exception e) {
e.printStackTrace();
logger.error("序列化对象异常[" + e.getMessage() + "]", e);
} finally {
close(objectOutputStream, byteArrayOutputStream);
}
return null;
}
@SuppressWarnings("unchecked")
public static <T> T unserialize(byte[] bytes) {
if (bytes == null)
return null;
ByteArrayInputStream byteArrayInputStream = null;
ObjectInputStream objectInputStream = null;
try {
byteArrayInputStream = new ByteArrayInputStream(bytes);
objectInputStream = new ObjectInputStream(byteArrayInputStream);
return (T) objectInputStream.readObject();
} catch (Exception e) {
e.printStackTrace();
} finally {
close(objectInputStream, byteArrayInputStream);
}
return null;
}
}
Redis的配置文件redis.properties如下:
#redis服务器ip# redis.ip=192.168.2.107 #redis服务器端口号# redis.port=6379 #********jedis池参数设置********# #jedis的最大分配对象# jedis.pool.maxActive=3000 #jedis最大保存idel状态对象数 # jedis.pool.maxIdle=1000 #jedis池没有对象返回时,最大等待时间 # jedis.pool.maxWait=1500 #jedis调用borrowObject方法时,是否进行有效检查# jedis.pool.testOnBorrow=true #jedis调用returnObject方法时,是否进行有效检查 # jedis.pool.testOnReturn=true
Mybatis使用Redis二级缓存的更多相关文章
- mybatis整合redis二级缓存
mybatis默认开启了二级缓存功能,在mybatis主配置文件中,将cacheEnabled设置成false,则会关闭二级缓存功能 <settings> <!--二级缓存默认开启, ...
- Spring Boot + Mybatis + Redis二级缓存开发指南
Spring Boot + Mybatis + Redis二级缓存开发指南 背景 Spring-Boot因其提供了各种开箱即用的插件,使得它成为了当今最为主流的Java Web开发框架之一.Mybat ...
- Mybatis一级、二级缓存
Mybatis一级.二级缓存 一级缓存 首先做一个测试,创建一个mapper配置文件和mapper接口,我这里用了最简单的查询来演示. <mapper namespace="c ...
- 【MyBatis学习13】MyBatis中的二级缓存
1. 二级缓存的原理 前面介绍了,mybatis中的二级缓存是mapper级别的缓存,值得注意的是,不同的mapper都有一个二级缓存,也就是说,不同的mapper之间的二级缓存是互不影响的.为了更加 ...
- springboot mybatis redis 二级缓存
前言 什么是mybatis二级缓存? 二级缓存是多个sqlsession共享的,其作用域是mapper的同一个namespace. 即,在不同的sqlsession中,相同的namespace下,相同 ...
- mybatis-自定义缓存-redis二级缓存
在mybatis一级缓存二级缓存中已经介绍过了二级缓存的大致原理.下面我们用redis来实现一下二级缓存.环境是springmvc+mybatis+redis 步骤一.引入redis相关的maven依 ...
- Mybatis自定义分布式二级缓存实现与遇到的一些问题解决方案!
先说两句: 我们都知道Mybatis缓存分两类: 一级缓存(同一个Session会话内) & 二级缓存(基于HashMap实现的以 namespace为范围的缓存) 今天呢, 我们不谈一级缓存 ...
- mybatis 细粒度控制二级缓存
本文要解决的问题:细粒度控制mybatis的二级缓存.mybatis的二级缓存的问题:当更新SQL执行时只清除当前SQL所在命名空间(namespace)的缓存.如果存在2个命名空间namespace ...
- mybatis(4)_二级缓存深入_使用第三方ehcache配置二级缓存
增删改对二级缓存的影响 1.增删改也会清空二级缓存 2.对于二级缓存的清空实质上是对value清空为null,key依然存在,并非将Entry<k,v>删除 3.从DB中进行select查 ...
随机推荐
- Docker与Android Studio的冲突问题
在行业内,VisualBox.VMware.Hyper-V冲突也不是什么秘密了 我在公司的电脑上先安装了Docker,并在安装Docker之前在BIOS中开启了虚拟化支持,所以在启动Docker时没有 ...
- 2018 icpc 徐州现场赛G-树上差分+组合数学-大佬的代码
现场赛大佬打印的代码,观摩了一哈. 写了注释,贴一下,好好学习.%%%PKU 代码: //树上差分(LCA) #include<bits/stdc++.h> #define For(i,x ...
- POJ 1679 The Unique MST 【最小生成树/次小生成树模板】
The Unique MST Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 22668 Accepted: 8038 D ...
- Python中sorted函数的用法(转)
[Python] sorted函数 我们需要对List.Dict进行排序,Python提供了两个方法 对给定的List L进行排序, 方法1.用List的成员函数sort进行排序,在本地进行排序,不返 ...
- 【UOJ #171】【WC 2016】挑战NPC
http://uoj.ac/problem/171 带花树开花时的u和v一定要记清楚顺序,想好了再写,数据范围也要算好! 对每个筐子拆成3个点,连成一个三元环,对每个(u,v),让u和v的3个点都连边 ...
- [Sgu395][bzoj2363]Binary Cat Club
一道神题…… rzO 发现立杰在初三(http://hi.baidu.com/wjbzbmr/item/4a50c7d8a8114911d78ed0a9据此可以推断)就怒A了此题…… Orz /*** ...
- C++中的读入输出优化及清新脱俗的宏命令
C和C++有了#define,从此它就变了模样 宏命令就是#define,#if,#error之类的 本文主要介绍宏命令和相关的骚操作 读入输出优化 inline int read() { int a ...
- [CODECHEF]LUCASTH
题意:设$f(n,k)=\sum\limits_{\substack{S\subseteq\{1,\cdots,n\}\\|S|=k}}\prod\limits_{x\in S}x$,问$f(n,0\ ...
- 【DFS】Gym - 100781A - Adjoin the Networks
给你一个森林,让你把它连接成一颗树,使得直径最小. 就求出每颗树的重心以后,全都往直径最大的那个的重心上连,一般情况是最大/2+次大/2+1,次大/2+第三大/2+2 中取较大者. 还有些特殊情况要特 ...
- 【贪心】Codeforces Round #423 (Div. 1, rated, based on VK Cup Finals) A. String Reconstruction
在每个给出的子串的起始位置打个标记,记录的是从这里开始的最长子串. 然后输出的时候就扫,如果遇到开始位置,就从这里开始输出,如果其后被更长的覆盖,就跳转到更长的串进行输出. 如果位置没被覆盖,就输出' ...