MyBatis学习——缓存机制

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='西安'}
第三 次结束

可以看到第三次就需要去数据库中查找了。

你可能感兴趣的:(MyBatis学习)