《深入理解mybatis原理(六)》 MyBatis缓存机制的设计与实现如何细粒度地控制你的MyBatis二级缓存
来源:互联网 发布:java文件系统下载 编辑:程序博客网 时间:2024/04/27 22:50
前几天网友chanfish 给我抛出了一个问题,笼统地讲就是如何能细粒度地控制MyBatis的二级缓存问题,酝酿了几天,觉得可以写个插件来实现这个这一功能。本文就是从问题入手,一步步分析现存的MyBatis的二级缓存的不足之处,探讨一点可以改进的地方,并且对不足之处开发一个插件进行弥补。
本文如下组织结构:
- 一个关于MyBatis的二级缓存的实际问题
- 当前MyBatis二级缓存的工作机制
- mybatis-enhanced-cache插件的设计和工作原理
- mybatis-enhanced-cache 插件的使用实例
1.一个关于MyBatis的二级缓存的实际问题
2. 当前MyBatis二级缓存的工作机制:
3.mybatis-enhanced-cache插件的设计和工作原理
4. mybatis-enhanced-cache 插件的使用实例:
1. 下载 mybatis-enhanced-cache.rar压缩包,解压,将其内的mybatis-enhanced-cache-0.0.1-SNAPSHOT.jar添加到项目的classpath下;
2. 配置MyBatis配置文件如下:
- <plugins>
- <plugin interceptor="org.luanlouis.mybatis.plugin.cache.EnhancedCachingExecutor">
- <property name="dependency" value="dependencys.xml"/>
- <property name="cacheEnabled" value="true"/>
- </plugin>
- </plugins>
其中,<property name="dependency"> 中的value属性是 StatementId之间的依赖关系的配置文件路径。
3. 配置StatementId之间的依赖关系
- <?xml version="1.0" encoding="UTF-8"?>
- <dependencies>
- <statements>
- <statement id="com.louis.mybatis.dao.DepartmentsMapper.updateByPrimaryKey">
- <observer id="com.louis.mybatis.dao.EmployeesMapper.selectWithDepartments" />
- </statement>
- </statements>
- </dependencies>
<statement>节点配置的是更新语句的statementId,其内的子节点<observer> 配置的是当更新语句执行后,应当清空缓存的查询语句的StatementId。子节点<observer>可以有多个。
如上的配置,则说明,如果"com.louis.mybatis.dao.DepartmentsMapper.updateByPrimaryKey" 更新语句执行后,由 “com.louis.mybatis.dao.EmployeesMapper.selectWithDepartments” 语句所产生的放置在Cache缓存中的数据都都会被清空。
4. 配置DepartmentsMapper.xml 和EmployeesMapper.xml
- <?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.louis.mybatis.dao.DepartmentsMapper" >
- <cache></cache>
- <resultMap id="BaseResultMap" type="com.louis.mybatis.model.Department" >
- <id column="DEPARTMENT_ID" property="departmentId" jdbcType="DECIMAL" />
- <result column="DEPARTMENT_NAME" property="departmentName" jdbcType="VARCHAR" />
- <result column="MANAGER_ID" property="managerId" jdbcType="DECIMAL" />
- <result column="LOCATION_ID" property="locationId" jdbcType="DECIMAL" />
- </resultMap>
- <sql id="Base_Column_List" >
- DEPARTMENT_ID, DEPARTMENT_NAME, MANAGER_ID, LOCATION_ID
- </sql>
- <update id="updateByPrimaryKey" parameterType="com.louis.mybatis.model.Department" >
- update HR.DEPARTMENTS
- set DEPARTMENT_NAME = #{departmentName,jdbcType=VARCHAR},
- MANAGER_ID = #{managerId,jdbcType=DECIMAL},
- LOCATION_ID = #{locationId,jdbcType=DECIMAL}
- where DEPARTMENT_ID = #{departmentId,jdbcType=DECIMAL}
- </update>
- <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer" >
- select
- <include refid="Base_Column_List" />
- from HR.DEPARTMENTS
- where DEPARTMENT_ID = #{departmentId,jdbcType=DECIMAL}
- </select>
- </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="com.louis.mybatis.dao.EmployeesMapper">
- <cache eviction="LRU" flushInterval="100000" size="10000"/>
- <resultMap id="BaseResultMap" type="com.louis.mybatis.model.Employee">
- <id column="EMPLOYEE_ID" jdbcType="DECIMAL" property="employeeId" />
- <result column="FIRST_NAME" jdbcType="VARCHAR" property="firstName" />
- <result column="LAST_NAME" jdbcType="VARCHAR" property="lastName" />
- <result column="EMAIL" jdbcType="VARCHAR" property="email" />
- <result column="PHONE_NUMBER" jdbcType="VARCHAR" property="phoneNumber" />
- <result column="HIRE_DATE" jdbcType="DATE" property="hireDate" />
- <result column="JOB_ID" jdbcType="VARCHAR" property="jobId" />
- <result column="SALARY" jdbcType="DECIMAL" property="salary" />
- <result column="COMMISSION_PCT" jdbcType="DECIMAL" property="commissionPct" />
- <result column="MANAGER_ID" jdbcType="DECIMAL" property="managerId" />
- <result column="DEPARTMENT_ID" jdbcType="DECIMAL" property="departmentId" />
- </resultMap>
- <sql id="Base_Column_List">
- EMPLOYEE_ID, FIRST_NAME, LAST_NAME, EMAIL, PHONE_NUMBER, HIRE_DATE, JOB_ID, SALARY,
- COMMISSION_PCT, MANAGER_ID, DEPARTMENT_ID
- </sql>
- <select id="selectWithDepartments" parameterType="java.lang.Integer" resultMap="BaseResultMap" useCache="true" >
- select
- *
- from HR.EMPLOYEES t left join HR.DEPARTMENTS S ON T.DEPARTMENT_ID = S.DEPARTMENT_ID
- where EMPLOYEE_ID = #{employeeId,jdbcType=DECIMAL}
- </select>
- </mapper>
5. 测试代码:
- package com.louis.mybatis.test;
- import java.io.InputStream;
- import java.util.Date;
- import java.util.HashMap;
- import java.util.Iterator;
- import java.util.List;
- import java.util.Map;
- import org.apache.ibatis.io.Resources;
- import org.apache.ibatis.session.SqlSession;
- import org.apache.ibatis.session.SqlSessionFactory;
- import org.apache.ibatis.session.SqlSessionFactoryBuilder;
- import org.apache.log4j.Logger;
- import com.louis.mybatis.model.Department;
- import com.louis.mybatis.model.Employee;
- /**
- * SqlSession 简单查询演示类
- * @author louluan
- */
- public class SelectDemo3 {
- private static final Logger loger = Logger.getLogger(SelectDemo3.class);
- public static void main(String[] args) throws Exception {
- InputStream inputStream = Resources.getResourceAsStream("mybatisConfig.xml");
- SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
- SqlSessionFactory factory = builder.build(inputStream);
- SqlSession sqlSession = factory.openSession(true);
- SqlSession sqlSession2 = factory.openSession(true);
- //3.使用SqlSession查询
- Map<String,Object> params = new HashMap<String,Object>();
- params.put("employeeId",10);
- //a.查询工资低于10000的员工
- Date first = new Date();
- //第一次查询
- List<Employee> result = sqlSession.selectList("com.louis.mybatis.dao.EmployeesMapper.selectWithDepartments",params);
- sqlSession.commit();
- checkCacheStatus(sqlSession);
- params.put("employeeId", 11);
- result = sqlSession.selectList("com.louis.mybatis.dao.EmployeesMapper.selectWithDepartments",params);
- sqlSession.commit();
- checkCacheStatus(sqlSession);
- params.put("employeeId", 12);
- result = sqlSession.selectList("com.louis.mybatis.dao.EmployeesMapper.selectWithDepartments",params);
- sqlSession.commit();
- checkCacheStatus(sqlSession);
- params.put("employeeId", 13);
- result = sqlSession.selectList("com.louis.mybatis.dao.EmployeesMapper.selectWithDepartments",params);
- sqlSession.commit();
- checkCacheStatus(sqlSession);
- Department department = sqlSession.selectOne("com.louis.mybatis.dao.DepartmentsMapper.selectByPrimaryKey",10);
- department.setDepartmentName("updated");
- sqlSession2.update("com.louis.mybatis.dao.DepartmentsMapper.updateByPrimaryKey", department);
- sqlSession.commit();
- checkCacheStatus(sqlSession);
- }
- public static void checkCacheStatus(SqlSession sqlSession)
- {
- loger.info("------------Cache Status------------");
- Iterator<String> iter = sqlSession.getConfiguration().getCacheNames().iterator();
- while(iter.hasNext())
- {
- String it = iter.next();
- loger.info(it+":"+sqlSession.getConfiguration().getCache(it).getSize());
- }
- loger.info("------------------------------------");
- }
- }
结果输出:
结果分析:
从上述的结果可以看出,前四次执行了“com.louis.mybatis.dao.EmployeesMapper.selectWithDepartments”语句,EmployeesMapper对应的Cache缓存中存储的结果缓存有1个增加到4个。
当执行了"com.louis.mybatis.dao.DepartmentsMapper.updateByPrimaryKey"后,EmployeeMapper对应的缓存Cache结果被清空了,即"com.louis.mybatis.dao.DepartmentsMapper.updateByPrimaryKey"更新语句引起了EmployeeMapper中的"com.louis.mybatis.dao.EmployeesMapper.selectWithDepartments"缓存的清空。
该插件的实现周期比较短,尚未经过性能方面的测试,如果果您对此插件有任何意见或者看法,可以留言一起交流和探讨。
该插件源码已经放到了Github上,可供大家自由修改,github地址:
https://github.com/LuanLouis/mybatis-enhanced-cache
本文转载自:http://blog.csdn.net/luanlouis/article/details/41800511
- 《深入理解mybatis原理(六)》 MyBatis缓存机制的设计与实现如何细粒度地控制你的MyBatis二级缓存
- 深入理解mybatis原理(六) MyBatis缓存机制的设计与实现如何细粒度地控制你的MyBatis二级缓存
- 《深入理解mybatis原理(六)》 MyBatis缓存机制的设计与实现如何细粒度地控制你的MyBatis二级缓存
- 如何细粒度地控制你的MyBatis二级缓存(mybatis-enhanced-cache插件实现)
- 如何细粒度地控制你的MyBatis二级缓存(mybatis-enhanced-cache插件实现)
- 如何细粒度地控制你的MyBatis二级缓存(mybatis-enhanced-cache插件实现)
- 《深入理解mybatis原理》 MyBatis缓存机制的设计与实现
- 《深入理解mybatis原理(五)》 MyBatis缓存机制的设计与实现
- 《深入理解mybatis原理》 MyBatis缓存机制的设计与实现
- 《深入理解mybatis原理》 MyBatis缓存机制的设计与实现
- 《深入理解mybatis原理》 MyBatis缓存机制的设计与实现
- 《深入理解mybatis原理》 MyBatis缓存机制的设计与实现
- 深入理解mybatis原理(五) MyBatis缓存机制的设计与实现
- 《深入理解mybatis原理》 MyBatis缓存机制的设计与实现
- 《深入理解mybatis原理》 MyBatis缓存机制的设计与实现
- 《深入理解mybatis原理》 MyBatis缓存机制的设计与实现
- 《深入理解mybatis原理》 MyBatis缓存机制的设计与实现
- SSM 之《深入理解mybatis原理》 MyBatis缓存机制的设计与实现
- Android提高第三篇之SurfaceView与多线程的混搭
- elasticsearch 自定义hash function (routing)
- jquery 遍历form 表单
- Android SD卡路径问题
- Android studio -SVN 使用笔记
- 《深入理解mybatis原理(六)》 MyBatis缓存机制的设计与实现如何细粒度地控制你的MyBatis二级缓存
- hibernate 实现多表连接查询
- 【LeetCode】268. Missing Number
- 排序
- UITextField —— 键盘弹出视图上移
- JAVA类加载机制全解析
- Dubbo的helloworld maven版
- 傻瓜式Gson解析
- 个人笔记-递归构造树