mybatis提供查询缓存,用于减轻数据库的压力,提高数据库的性能
Mybatis的一级缓存是SQLSession级别的缓存、mybatis默认是开启一级缓存的。在SQLSession实例对象下存在一个数据结构(HashMap),用户进行存储缓存数据,不同的SQLSession有各自的缓存数据区域,它们之间互不影响。
用法:
在同一个sqlSession中两次执行相同的sql语句,第一次执行完毕会将数据库中查询的数据写到缓存(内
存),第二次会从缓存中获取数据将不再从数据库查询,从而提高查询效率。当一个sqlSession结束后该
sqlSession中的一级缓存也就不存在了。当数据库发生变更操作(insert、update、delete)操作时,会将缓
存数据删除。这样做的目标是避免缓存数据和数据库数据不一致,读取脏数据
实际操作:
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
System.out.println("第一次开始");
User user = userMapper.getUserByID(1);
System.out.println(user.toString());
System.out.println("第一次结束");
System.out.println("第二次开始");
User user1 = userMapper.getUserByID(1);
System.out.println(user.toString());
System.out.println("第二次结束");
第一次开始
2019-06-16-17:28:54,299 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction] [DEBUG] - Opening JDBC Connection
2019-06-16-17:28:54,828 [main] [org.apache.ibatis.datasource.pooled.PooledDataSource] [DEBUG] - Created connection 182738614.
2019-06-16-17:28:54,829 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction] [DEBUG] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@ae45eb6]
2019-06-16-17:28:54,833 [main] [com.wj.dao.UserMapper.getUserByID] [DEBUG] - ==> Preparing: select * from user where id = ?
2019-06-16-17:28:54,951 [main] [com.wj.dao.UserMapper.getUserByID] [DEBUG] - ==> Parameters: 1(Integer)
2019-06-16-17:28:54,986 [main] [com.wj.dao.UserMapper.getUserByID] [DEBUG] - <== Total: 1
User{id=1, name='wj', sex='19', address='西安'}
第一次结束
第二次开始
User{id=1, name='wj', sex='19', address='西安'}
第二次结束
从结果可以看出,第二次查询的时候并没有去数据库里面进行查询。
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
System.out.println("第一次开始");
User user = userMapper.getUserByID(1);
System.out.println(user.toString());
System.out.println("第一次结束");
User user2 = new User(6,"w","男","陕西");
userMapper.InsertUser(user2);
System.out.println("第二次开始");
User user1 = userMapper.getUserByID(1);
System.out.println(user1.toString());
System.out.println("第二次结束");
第一次开始
2019-06-16-17:32:12,109 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction] [DEBUG] - Opening JDBC Connection
2019-06-16-17:32:12,629 [main] [org.apache.ibatis.datasource.pooled.PooledDataSource] [DEBUG] - Created connection 182738614.
2019-06-16-17:32:12,630 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction] [DEBUG] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@ae45eb6]
2019-06-16-17:32:12,633 [main] [com.wj.dao.UserMapper.getUserByID] [DEBUG] - ==> Preparing: select * from user where id = ?
2019-06-16-17:32:12,748 [main] [com.wj.dao.UserMapper.getUserByID] [DEBUG] - ==> Parameters: 1(Integer)
2019-06-16-17:32:12,787 [main] [com.wj.dao.UserMapper.getUserByID] [DEBUG] - <== Total: 1
User{id=1, name='wj', sex='19', address='西安'}
第一次结束
2019-06-16-17:32:12,789 [main] [com.wj.dao.UserMapper.InsertUser] [DEBUG] - ==> Preparing: insert into user (id, name, sex, address ) values ( ?,?, ?, ? )
2019-06-16-17:32:12,791 [main] [com.wj.dao.UserMapper.InsertUser] [DEBUG] - ==> Parameters: 6(Integer), w(String), 男(String), 陕西(String)
2019-06-16-17:32:12,792 [main] [com.wj.dao.UserMapper.InsertUser] [DEBUG] - <== Updates: 1
第二次开始
2019-06-16-17:32:12,793 [main] [com.wj.dao.UserMapper.getUserByID] [DEBUG] - ==> Preparing: select * from user where id = ?
2019-06-16-17:32:12,793 [main] [com.wj.dao.UserMapper.getUserByID] [DEBUG] - ==> Parameters: 1(Integer)
2019-06-16-17:32:12,795 [main] [com.wj.dao.UserMapper.getUserByID] [DEBUG] - <== Total: 1
User{id=1, name='wj', sex='19', address='西安'}
第二次结束
我们看到了进行插入操作后,第二次查询只能去数据库进行查询了。
二级缓存是mapper级别的缓存,多个SqlSession去操作同一个Mapper的sql语句,多个SqlSession去操作数据库得到数据会存在二级缓存区域,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession的。
当开一个会话时,一个SqlSession对象会使用一个Executor对象来完成会话操作,MyBatis的二级缓存机制的关键就是对这个Executor对象做文章 如果用户配置了cacheEnabled=true,那么MyBatis在为SqlSession对象创建Executor对象时,会对Executor对象加上一个装饰者:CachingExecutor,这时SqlSession使用CachingExecutor对象来完成操作请求 CachingExecutor对于查询请求,会先判断该查询请求在Application级别的二级缓存中是否有缓存结果
如果有查询结果,则直接返回缓存结果
如果缓存中没有,再交给真正的Executor对象来完成查询操作,之后CachingExecutor会将真正Executor返回的查询结果放置到缓存中,然后在返回给用户
mybatis二级缓存,必须sqlsession.close 或者commit后,才能把第一次查询的结果提交,才会写入缓存里面
在全局配置中配置开启二级缓存
在mapper.xml文件中打开缓存
eviction表示缓存淘汰策略
LRU:最近最少使用
SqlSession sqlSession1 = sqlSessionFactory.openSession();
SqlSession sqlSession = sqlSessionFactory.openSession();
SqlSession sqlSession2 = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);
UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);
System.out.println("第一次开始");
User user = userMapper.getUserByID(1);
System.out.println(user.toString());
System.out.println("第一次结束");
sqlSession.close();
System.out.println("第二次开始");
User user1 = userMapper1.getUserByID(1);
System.out.println(user1.toString());
System.out.println("第二 次结束");
第一次开始
2019-06-16-17:40:56,362 [main] [com.wj.dao.UserMapper] [DEBUG] - Cache Hit Ratio [com.wj.dao.UserMapper]: 0.0
2019-06-16-17:40:56,379 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction] [DEBUG] - Opening JDBC Connection
2019-06-16-17:40:56,978 [main] [org.apache.ibatis.datasource.pooled.PooledDataSource] [DEBUG] - Created connection 87765719.
2019-06-16-17:40:56,978 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction] [DEBUG] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@53b32d7]
2019-06-16-17:40:56,983 [main] [com.wj.dao.UserMapper.getUserByID] [DEBUG] - ==> Preparing: select * from user where id = ?
2019-06-16-17:40:57,038 [main] [com.wj.dao.UserMapper.getUserByID] [DEBUG] - ==> Parameters: 1(Integer)
2019-06-16-17:40:57,119 [main] [com.wj.dao.UserMapper.getUserByID] [DEBUG] - <== Total: 1
User{id=1, name='wj', sex='19', address='西安'}
第一次结束
2019-06-16-17:40:57,146 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction] [DEBUG] - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@53b32d7]
2019-06-16-17:40:57,146 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction] [DEBUG] - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@53b32d7]
2019-06-16-17:40:57,147 [main] [org.apache.ibatis.datasource.pooled.PooledDataSource] [DEBUG] - Returned connection 87765719 to pool.
第二次开始
2019-06-16-17:40:57,266 [main] [com.wj.dao.UserMapper] [DEBUG] - Cache Hit Ratio [com.wj.dao.UserMapper]: 0.5
User{id=1, name='wj', sex='19', address='西安'}
第二 次结束
此时已经命中缓存了
SqlSession sqlSession1 = sqlSessionFactory.openSession();
SqlSession sqlSession = sqlSessionFactory.openSession();
SqlSession sqlSession2 = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);
UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);
System.out.println("第一次开始");
User user = userMapper.getUserByID(1);
System.out.println(user.toString());
System.out.println("第一次结束");
sqlSession.close();
System.out.println("第二次开始");
User user1 = userMapper1.getUserByID(1);
System.out.println(user1.toString());
System.out.println("第二 次结束");
User user2 = new User(10,"w","男","陕西");
userMapper1.InsertUser(user2);
sqlSession1.commit();
System.out.println("第三次开始");
User user3 = userMapper2.getUserByID(1);
System.out.println(user3.toString());
System.out.println("第三 次结束");
第一次开始
2019-06-16-17:46:34,598 [main] [com.wj.dao.UserMapper] [DEBUG] - Cache Hit Ratio [com.wj.dao.UserMapper]: 0.0
2019-06-16-17:46:34,611 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction] [DEBUG] - Opening JDBC Connection
2019-06-16-17:46:35,086 [main] [org.apache.ibatis.datasource.pooled.PooledDataSource] [DEBUG] - Created connection 87765719.
2019-06-16-17:46:35,087 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction] [DEBUG] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@53b32d7]
2019-06-16-17:46:35,091 [main] [com.wj.dao.UserMapper.getUserByID] [DEBUG] - ==> Preparing: select * from user where id = ?
2019-06-16-17:46:35,154 [main] [com.wj.dao.UserMapper.getUserByID] [DEBUG] - ==> Parameters: 1(Integer)
2019-06-16-17:46:35,211 [main] [com.wj.dao.UserMapper.getUserByID] [DEBUG] - <== Total: 1
User{id=1, name='wj', sex='19', address='西安'}
第一次结束
2019-06-16-17:46:35,235 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction] [DEBUG] - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@53b32d7]
2019-06-16-17:46:35,235 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction] [DEBUG] - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@53b32d7]
2019-06-16-17:46:35,236 [main] [org.apache.ibatis.datasource.pooled.PooledDataSource] [DEBUG] - Returned connection 87765719 to pool.
第二次开始
2019-06-16-17:46:35,358 [main] [com.wj.dao.UserMapper] [DEBUG] - Cache Hit Ratio [com.wj.dao.UserMapper]: 0.5
User{id=1, name='wj', sex='19', address='西安'}
第二 次结束
2019-06-16-17:46:35,359 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction] [DEBUG] - Opening JDBC Connection
2019-06-16-17:46:35,359 [main] [org.apache.ibatis.datasource.pooled.PooledDataSource] [DEBUG] - Checked out connection 87765719 from pool.
2019-06-16-17:46:35,359 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction] [DEBUG] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@53b32d7]
2019-06-16-17:46:35,360 [main] [com.wj.dao.UserMapper.InsertUser] [DEBUG] - ==> Preparing: insert into user (id, name, sex, address ) values ( ?,?, ?, ? )
2019-06-16-17:46:35,361 [main] [com.wj.dao.UserMapper.InsertUser] [DEBUG] - ==> Parameters: 10(Integer), w(String), 男(String), 陕西(String)
2019-06-16-17:46:35,362 [main] [com.wj.dao.UserMapper.InsertUser] [DEBUG] - <== Updates: 1
2019-06-16-17:46:35,362 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction] [DEBUG] - Committing JDBC Connection [com.mysql.jdbc.JDBC4Connection@53b32d7]
第三次开始
2019-06-16-17:46:35,408 [main] [com.wj.dao.UserMapper] [DEBUG] - Cache Hit Ratio [com.wj.dao.UserMapper]: 0.3333333333333333
2019-06-16-17:46:35,408 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction] [DEBUG] - Opening JDBC Connection
2019-06-16-17:46:35,428 [main] [org.apache.ibatis.datasource.pooled.PooledDataSource] [DEBUG] - Created connection 1033490990.
2019-06-16-17:46:35,429 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction] [DEBUG] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@3d99d22e]
2019-06-16-17:46:35,430 [main] [com.wj.dao.UserMapper.getUserByID] [DEBUG] - ==> Preparing: select * from user where id = ?
2019-06-16-17:46:35,430 [main] [com.wj.dao.UserMapper.getUserByID] [DEBUG] - ==> Parameters: 1(Integer)
2019-06-16-17:46:35,432 [main] [com.wj.dao.UserMapper.getUserByID] [DEBUG] - <== Total: 1
User{id=1, name='wj', sex='19', address='西安'}
第三 次结束
可以看到第三次就需要去数据库中查找了。