AAA spring 集成mybatis使用二级缓存 (下篇)
来源:互联网 发布:java测试 博客园 编辑:程序博客网 时间:2024/05/23 01:31
先看《spring 集成mybatis》和《Mybatis一级缓存》,在此基础上进行修改。
集成了spring之后,似乎没有办法直接使用一级缓存了,但是二级缓存还是可以的。
当你第一次执行的时候Cache Hit Ratio 0
第二次执行的时候就 Cache Hit Ratio 0.5
使用二级缓存只需要更改;两处地方
1 avaBean序列化,
2 映射xml文件里面添加<cache/>
一、实体类
二、userMapper.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.mapper.UserMapper">
<cache/>
<resultMap type="User" id="userResult">
<result column="user_id" property="id"/>
<result column="user_name" property="name"/>
<result column="user_birthday" property="birthday"/>
<result column="user_salary" property="salary"/>
</resultMap>
<!-- 取得插入数据后的 id -->
<insert id="save" keyColumn="user_id" keyProperty="id" useGeneratedKeys="true">
insert into s_user(user_name,user_birthday,user_salary)
values(#{name},#{birthday},#{salary})
</insert>
<update id="update">
update s_user
set user_name = #{name},
user_birthday = #{birthday},
user_salary = #{salary}
where user_id = #{id}
</update>
<delete id="delete">
delete from s_user
where user_id = #{id}
</delete>
<select id="findById" resultMap="userResult">
select *
from s_user
where user_id = #{id}
</select>
<select id="findAll" resultMap="userResult">
select *
from s_user
</select>
</mapper>
同样加上<cache/>就可以了。
三、测试方法
2015-05-09 18:07:11,062 [main] DEBUG [org.mybatis.spring.SqlSessionUtils] - Creating a new SqlSession
2015-05-09 18:07:11,078 [main] DEBUG [org.mybatis.spring.SqlSessionUtils] - SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1425f38] was not registered for synchronization because synchronization is not active
2015-05-09 18:07:11,156 [main] DEBUG [org.springframework.jdbc.datasource.DataSourceUtils] - Fetching JDBC Connection from DataSource
2015-05-09 18:07:11,156 [main] DEBUG [org.springframework.jdbc.datasource.DriverManagerDataSource] - Creating new JDBC DriverManager Connection to [jdbc:mysql://localhost:3306/mybatis]
2015-05-09 18:07:11,171 [main] DEBUG [org.mybatis.spring.transaction.SpringManagedTransaction] - JDBC Connection [com.mysql.jdbc.JDBC4Connection@a0afab] will not be managed by Spring
2015-05-09 18:07:11,171 [main] DEBUG [com.mapper.UserMapper.findById] - ooo Using Connection [com.mysql.jdbc.JDBC4Connection@a0afab]
2015-05-09 18:07:11,187 [main] DEBUG [com.mapper.UserMapper.findById] - ==> Preparing: select * from s_user where user_id = ?
2015-05-09 18:07:11,234 [main] DEBUG [com.mapper.UserMapper.findById] - ==> Parameters: 1(Integer)
2015-05-09 18:07:11,296 [main] DEBUG [org.mybatis.spring.SqlSessionUtils] - Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1425f38]
2015-05-09 18:07:11,296 [main] DEBUG [org.springframework.jdbc.datasource.DataSourceUtils] - Returning JDBC Connection to DataSource
User [id=1, name=marry, birthday=Sat Apr 18 00:00:00 CST 2015, salary=2000.0]
2015-05-09 18:07:11,296 [main] DEBUG [org.mybatis.spring.SqlSessionUtils] - Creating a new SqlSession
2015-05-09 18:07:11,296 [main] DEBUG [org.mybatis.spring.SqlSessionUtils] - SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1905742] was not registered for synchronization because synchronization is not active
2015-05-09 18:07:11,312 [main] DEBUG [org.mybatis.spring.SqlSessionUtils] - Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1905742]
User [id=1, name=marry, birthday=Sat Apr 18 00:00:00 CST 2015, salary=2000.0]
可以看到,spring默认在查询完就关闭了SqlSession,所以想要用一级缓存就很难了。
然后也看到第二次查询并没有去获取JDBC连接。
三、Cache使用时的注意事项
1. 只能在【只有单表操作】的表上使用缓存
不只是要保证这个表在整个系统中只有单表操作,而且和该表有关的全部操作必须全部在一个namespace
下。
2. 在可以保证查询远远大于insert,update,delete操作的情况下使用缓存
这一点不需要多说,所有人都应该清楚。记住,这一点需要保证在1的前提下才可以!
四、避免使用二级缓存
可能会有很多人不理解这里,二级缓存带来的好处远远比不上他所隐藏的危害。
缓存是以
namespace
为单位的,不同namespace
下的操作互不影响。insert,update,delete操作会清空所在
namespace
下的全部缓存。通常使用MyBatis Generator生成的代码中,都是各个表独立的,每个表都有自己的
namespace
。
为什么避免使用二级缓存
在符合【Cache使用时的注意事项】的要求时,并没有什么危害。
其他情况就会有很多危害了。
针对一个表的某些操作不在他独立的namespace
下进行。
例如在UserMapper.xml
中有大多数针对user
表的操作。但是在一个XXXMapper.xml
中,还有针对user
单表的操作。
这会导致user
在两个命名空间下的数据不一致。如果在UserMapper.xml
中做了刷新缓存的操作,在XXXMapper.xml
中缓存仍然有效,如果有针对user
的单表查询,使用缓存的结果可能会不正确。
更危险的情况是在XXXMapper.xml
做了insert,update,delete操作时,会导致UserMapper.xml
中的各种操作充满未知和风险。
有关这样单表的操作可能不常见。但是你也许想到了一种常见的情况。
多表操作一定不能使用缓存
为什么不能?
首先不管多表操作写到那个namespace
下,都会存在某个表不在这个namespace
下的情况。
例如两个表:role
和user_role
,如果我想查询出某个用户的全部角色role
,就一定会涉及到多表的操作。
像上面这个查询,你会写到那个xml中呢??
不管是写到RoleMapper.xml
还是UserRoleMapper.xml
,或者是一个独立的XxxMapper.xml
中。如果使用了二级缓存,都会导致上面这个查询结果可能不正确。
如果你正好修改了这个用户的角色,上面这个查询使用缓存的时候结果就是错的。
这点应该很容易理解。
在我看来,就以MyBatis目前的缓存方式来看是无解的。多表操作根本不能缓存。
如果你让他们都使用同一个namespace
(通过<cache-ref>
)来避免脏数据,那就失去了缓存的意义。
看到这里,实际上就是说,二级缓存不能用。整篇文章介绍这么多也没什么用了。
五、挽救二级缓存?
想更高效率的使用二级缓存是解决不了了。
但是解决多表操作避免脏数据还是有法解决的。解决思路就是通过拦截器判断执行的sql涉及到那些表(可以用jsqlparser解析),然后把相关表的缓存自动清空。但是这种方式对缓存的使用效率是很低的。
设计这样一个插件是相当复杂的,既然我没想着去实现,就不废话了。
最后还是建议,放弃二级缓存,在业务层使用可控制的缓存代替更好。
- AAA spring 集成mybatis使用二级缓存 (下篇)
- spring 集成mybatis使用二级缓存
- Redis集成到Spring做mybatis做二级缓存
- mybatis 和集成Spring使用
- Spring(五)使用Spring集成MyBatis
- Spring(五)使用Spring集成MyBatis
- MyBatis使用二级缓存
- Mybatis二级缓存的使用
- Mybatis的二级缓存使用
- mybatis二级缓存简单使用
- Spring boot使用Redis集群替换mybatis二级缓存
- mybatis + spring + redis(二级缓存)整合
- Spring Boot + Mybatis + Redis二级缓存
- Spring Boot + Mybatis + Redis二级缓存
- Spring Boot + Mybatis + Redis二级缓存
- AAA在Spring下集成ActiveMQ
- mybatis的二级缓存sessionFactory缓存集成redis
- spring-boot 集成mybatis配置使用
- 网络互联参考模型
- HTTP Content-type 对照表
- codeforces-82A-Double Cola( 等比数列 + 有意思的题目! )
- Elasticsearch python API 文档Documentation 2.3.0 by Honza Král
- :元素大小与位置offsetLeft offsetTop offsetWidth offsetHeight clientWidth clientHeight scrollWidth scrollHei
- AAA spring 集成mybatis使用二级缓存 (下篇)
- LeetCode 226 Invert Binary Tree JAVA
- 马尔可夫网络,(马尔可夫随机场、无向图模型)(Markov Random Field)
- gcc编译器 CFLAGS 标志参数说明
- 蓝桥杯练习系统 Lift and throw
- linux gdb调试
- 深入剖析Java中的装箱和拆箱
- spring加载配置文件
- SQL2008 的收缩日志&log日志丢失恢复