现在MyBatis
因其灵活性使用率很高,而且MyBatis
也提供缓存功能,所以也可了解一下。MyBatis
提供一级缓存和二级缓存,一级缓存(同一个sqlSession
共享数据)是默认开启的而且不能关闭,二级缓存(不同的sqlSession
之间共享数据)是需要配置开启的。
一级缓存是默认开启的,只要是同一个sqlSession
,第二次查询就会从缓存中读取数据。不过如果跟Spring
集成后,一级缓存就会失效。原因就是MyBatis
的一级缓存是需要同一个sqlSession
,但是Spring
会在sqlSession
使用完毕后就会关闭,这样缓存数据将会清空。当第二个请求,重新新建sqlSession
,然后又去请求数据库。目前我们一般是跟Spring
整合使用,但是因为这个原因只能寻求其二级缓存。
一级缓存无法实现,但是MyBatis
提供二级缓存,而且配置比较简单,首先需要返回的POJO类
必须可序列化,即要求实现Serializable接口
,然后在XML文件中配置
配置缓存可以使用不同的参数:
eviction
代表缓存回收策略,目前MyBatis提供以下回收策略。(1)LRU,最近最少使用的,移除最长时间不用的对象。(2)FIFO,先进先出,按对象进入缓存的顺序来移除他们。(3)SOFT,软引用,移除基于垃圾回收器状态和软引用规则的对象。(4)WEAK,弱引用,更积极地移除基于垃圾收集器状态和弱引用规则的对象。flushInterval
刷新间隔时间,单位为毫秒,如果不配置,那么当SQL被执行的时候才会去刷新缓存。size
引用数目,代表缓存最多可以存储多少对象,不宜设置过大,不然会导致内存溢出。readOnly
只读,意味着缓存数据只能读取而不能修改。全局配置:默认就是true,一般不用配置,配置就是取消二级缓存,意义不大。
局部配置:使用useCache
和flushCache
,前者表示是否需要使用缓存,而后者表示插入后是否需要刷新缓存。
(1) 多个namespace不要操作同一张表
二级缓存中的数据是基于namespace的,不同的namespace的数据互不干扰,如果某namespace中的进行增删改而造成缓存刷新,只会引起该namespace中的二级缓存数据刷新,不会对其他namespace下的数据有影响,所以从其他namespace中读取的数据还是未更新的。
(2)不要在关联关系表上执行增删改操作
一个namespace一般是同一个表进行操作,若表间存在关联关系,也就意味着同一个表可能出现在多个namespace下,这样就会存在上述讲到的风险。
(3)查询多于修改时使用二级缓存
二级缓存频繁刷新容易降低系统性能。
Department.java
public class Department implements Serializable
DepartmentMapper.xml
测试
@Test
public void testDepartment(){
try {
System.out.println("=================================");
MvcResult result1=mockMvc.perform(MockMvcRequestBuilders
.get("/depts"))
.andReturn();
MvcResult result2=mockMvc.perform(MockMvcRequestBuilders
.get("/depts"))
.andReturn();
System.out.println(result1.getResponse().getContentAsString());
System.out.println(result2.getResponse().getContentAsString());
System.out.println("=================================");
} catch (Exception e) {
e.printStackTrace();
}
}
结果
.
.
.
2023-09-01 11:46:44,987 [main] DEBUG [org.mybatis.spring.SqlSessionUtils] - Creating a new SqlSession
2023-09-01 11:46:45,012 [main] DEBUG [org.mybatis.spring.SqlSessionUtils] - Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2063c53e]
2023-09-01 11:46:45,075 [main] DEBUG [com.plf.hello.dao.DepartmentMapper] - Cache Hit Ratio [com.plf.hello.dao.DepartmentMapper]: 0.0
2023-09-01 11:46:45,085 [main] DEBUG [org.mybatis.spring.transaction.SpringManagedTransaction] - JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@5ce4369b] will be managed by Spring
2023-09-01 11:46:45,095 [main] DEBUG [com.plf.hello.dao.DepartmentMapper.selectByExample] - ==> Preparing: select dept_id, dept_name from tbl_dept
2023-09-01 11:46:45,149 [main] DEBUG [com.plf.hello.dao.DepartmentMapper.selectByExample] - ==> Parameters:
2023-09-01 11:46:45,216 [main] DEBUG [com.plf.hello.dao.DepartmentMapper.selectByExample] - <== Total: 2
2023-09-01 11:46:45,217 [main] DEBUG [com.alibaba.druid.pool.PreparedStatementPool] - {conn-10001, pstmt-20000} enter cache
2023-09-01 11:46:45,218 [main] DEBUG [org.mybatis.spring.SqlSessionUtils] - Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2063c53e]
2023-09-01 11:46:45,218 [main] DEBUG [org.mybatis.spring.SqlSessionUtils] - Transaction synchronization committing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2063c53e]
2023-09-01 11:46:45,301 [main] DEBUG [org.mybatis.spring.SqlSessionUtils] - Transaction synchronization deregistering SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2063c53e]
2023-09-01 11:46:45,301 [main] DEBUG [org.mybatis.spring.SqlSessionUtils] - Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2063c53e]
2023-09-01 11:46:45,301 [main] DEBUG [org.springframework.jdbc.datasource.DataSourceTransactionManager] - Initiating transaction commit
2023-09-01 11:46:45,301 [main] DEBUG [org.springframework.jdbc.datasource.DataSourceTransactionManager] - Committing JDBC transaction on Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@5ce4369b]
2023-09-01 11:46:45,306 [main] DEBUG [org.springframework.jdbc.datasource.DataSourceTransactionManager] - Releasing JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@5ce4369b] after transaction
.
.
.
2023-09-01 11:46:45,493 [main] DEBUG [com.plf.hello.dao.DepartmentMapper] - Cache Hit Ratio [com.plf.hello.dao.DepartmentMapper]: 0.5
2023-09-01 11:46:45,493 [main] DEBUG [org.mybatis.spring.SqlSessionUtils] - Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@4248e66b]
2023-09-01 11:46:45,493 [main] DEBUG [org.mybatis.spring.SqlSessionUtils] - Transaction synchronization committing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@4248e66b]
2023-09-01 11:46:45,493 [main] DEBUG [org.mybatis.spring.SqlSessionUtils] - Transaction synchronization deregistering SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@4248e66b]
2023-09-01 11:46:45,493 [main] DEBUG [org.mybatis.spring.SqlSessionUtils] - Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@4248e66b]
2023-09-01 11:46:45,493 [main] DEBUG [org.springframework.jdbc.datasource.DataSourceTransactionManager] - Initiating transaction commit
2023-09-01 11:46:45,493 [main] DEBUG [org.springframework.jdbc.datasource.DataSourceTransactionManager] - Committing JDBC transaction on Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@5ce4369b]
2023-09-01 11:46:45,497 [main] DEBUG [org.springframework.jdbc.datasource.DataSourceTransactionManager] - Releasing JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@5ce4369b] after transaction
.
.
.
{"code":100,"msg":"处理成功","extend":{"depts":[{"deptId":1,"deptName":"技术部"},{"deptId":2,"deptName":"餐饮部"}]}}
{"code":100,"msg":"处理成功","extend":{"depts":[{"deptId":1,"deptName":"技术部"},{"deptId":2,"deptName":"餐饮部"}]}}
上述结果可知使用二级缓存,只请求了一次SQL语句,其中Cache Hit Ratio [com.plf.hello.dao.DepartmentMapper]: 0.5
显示缓存命中率0.5。
MyBatis毕竟是用于操作SQL的,在缓存方面肯定不如其他的缓存更实用,目前比较多的就是Ehcache、Redis、MongoDB等用作缓存,这里主要实现Spring+Ehcache的缓存
pom.xml
net.sf.ehcache
ehcache-core
2.6.11
ehcache.xml
applicationContext.xml
xmlns:cache="http://www.springframework.org/schema/cache"
xsi:schemaLocation="http://www.springframework.org/schema/cache
http://www.springframework.org/schema/cache/spring-cache-4.3.xsd"
DepartmentService.java
@Cacheable(value = "myCache")
public List getDepts() {
return departmentMapper.selectByExample(null);
}