1. 一级缓存

    ​ MyBatis一级缓存上SqlSession缓存,即在统一SqlSession中,在不执行增删改操作提交事务的前提下,对同一条数据进行多次查询时,第一次查询从数据库中查询,完成后会存入缓存,其余从缓存中直接读取。MyBatis一级缓存默认开启。

  2. 二级缓存

    ​ MyBatis二级缓存是命名空间NameSpace缓存,也可理解为二级缓存被多个SqlSession共享,是一个全局变量。

    ​ 二级缓存默认是关闭的,需要手动配置进行开启。开启二级缓存后,数据查询流程为:二级缓存->一级缓存->数据库。

    • 二级缓存开启

      1. 实体类需要实现Serializable接口

      2. 核心配置文件增加标签

      <settings>
      <setting name="cacheEnabled" value="true"/>
      </settings>
      1. 在需要开启的mapper中添加标签
      <!--开启二级缓存-->
      <cache/>
      • eviction属性可以设置缓存回收策略,默认LRU策略

        • LRU - 最近最少回收,移除最长时间不被使用的对象
        • FIFO - 先进先出,按照缓存进入的顺序来移除它们
        • SOFT - 软引用,移除基于垃圾回收器状态和软引用规则的对象
        • WEAK - 弱引用,更积极的移除基于垃圾收集器和弱引用规则的对象
      • flushinterval 缓存刷新间隔,缓存多长时间刷新一次,默认不清空,设置一个毫秒值

      • readOnly: 是否只读;

        false读写(默认):MyBatis 觉得数据可能会被修改

        true 只读,MyBatis 认为所有从缓存中获取数据的操作都是只读操作,不会修改数据。MyBatis 为了加快获取数据,直接就会将数据在缓存中的引用交给用户。不安全,速度快。

      • size : 缓存存放多少个元素

      • type: 指定自定义缓存的全类名(实现Cache 接口即可)

      • blocking: 若缓存中找不到对应的key,是否会一直blocking,直到有对应的数据进入缓存。

        例如:

        <cache eviction="LRU" flushInterval="1000*60*60*24*7" readOnly="true" blocking="false" type="MyCache" size="1000"/>
    • 二级缓存测试,多个SqlSession

      InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
      SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); User param = new User();
      param.setId(1); SqlSession sqlSession1 = sqlSessionFactory.openSession();
      IUserDao userDao1 = sqlSession1.getMapper(IUserDao.class);
      User user1 = userDao1.findOne(param);
      System.out.println(user1);
      sqlSession1.close(); SqlSession sqlSession2 = sqlSessionFactory.openSession();
      IUserDao userDao2 = sqlSession2.getMapper(IUserDao.class);
      User user2 = userDao2.findOne(param);
      System.out.println(user2);
      sqlSession2.close();

      控制台查看输出日志,发现缓存已命中—Cache Hit Ratio [com.rangers.dao.IUserDao]: 0.5

      14:26:48,608 DEBUG IUserDao:62 - Cache Hit Ratio [com.rangers.dao.IUserDao]: 0.0
      14:26:48,611 DEBUG JdbcTransaction:137 - Opening JDBC Connection
      14:26:48,952 DEBUG PooledDataSource:406 - Created connection 543846639.
      14:26:48,952 DEBUG JdbcTransaction:101 - Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@206a70ef]
      14:26:48,957 DEBUG findOne:159 - ==> Preparing: select * from user where id=?
      14:26:48,980 DEBUG findOne:159 - ==> Parameters: 1(Integer)
      14:26:49,004 DEBUG findOne:159 - <== Total: 1
      com.rangers.entity.User{id=1, name='rangers', address='杭州'}
      14:26:49,007 DEBUG JdbcTransaction:123 - Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@206a70ef]
      14:26:49,010 DEBUG JdbcTransaction:91 - Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@206a70ef]
      14:26:49,011 DEBUG PooledDataSource:363 - Returned connection 543846639 to pool.
      14:26:49,014 DEBUG IUserDao:62 - Cache Hit Ratio [com.rangers.dao.IUserDao]: 0.5
      com.rangers.entity.User{id=1, name='rangers', address='杭州'}
    • 二级缓存失效条件

      • 首次SqlSession未提交事务时,二级缓存无法命中

        SqlSession未提交时,执行结果未放入二级缓存中,这时候第二个SqlSession在查询时候是无法命中的

        例如:调整sqlSession1.close();在sqlSession2执行之后,就不会命中缓存

        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); User param = new User();
        param.setId(1); SqlSession sqlSession1 = sqlSessionFactory.openSession();
        IUserDao userDao1 = sqlSession1.getMapper(IUserDao.class);
        User user1 = userDao1.findOne(param);
        System.out.println(user1); SqlSession sqlSession2 = sqlSessionFactory.openSession();
        IUserDao userDao2 = sqlSession2.getMapper(IUserDao.class);
        User user2 = userDao2.findOne(param);
        System.out.println(user2); sqlSession1.close();
        sqlSession2.close();

        查看控制台输出,发现两次缓存命中都是0.0,Cache Hit Ratio [com.rangers.dao.IUserDao]: 0.0

        14:49:39,073 DEBUG IUserDao:62 - Cache Hit Ratio [com.rangers.dao.IUserDao]: 0.0
        14:49:39,075 DEBUG JdbcTransaction:137 - Opening JDBC Connection
        14:49:39,385 DEBUG PooledDataSource:406 - Created connection 543846639.
        14:49:39,385 DEBUG JdbcTransaction:101 - Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@206a70ef]
        14:49:39,389 DEBUG findOne:159 - ==> Preparing: select * from user where id=?
        14:49:39,408 DEBUG findOne:159 - ==> Parameters: 1(Integer)
        14:49:39,433 DEBUG findOne:159 - <== Total: 1
        com.rangers.entity.User{id=1, name='rangers', address='杭州'}
        14:49:39,434 DEBUG IUserDao:62 - Cache Hit Ratio [com.rangers.dao.IUserDao]: 0.0
        14:49:39,434 DEBUG JdbcTransaction:137 - Opening JDBC Connection
        14:49:39,489 DEBUG PooledDataSource:406 - Created connection 2079179914.
        14:49:39,489 DEBUG JdbcTransaction:101 - Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@7bedc48a]
        14:49:39,491 DEBUG findOne:159 - ==> Preparing: select * from user where id=?
        14:49:39,492 DEBUG findOne:159 - ==> Parameters: 1(Integer)
        14:49:39,495 DEBUG findOne:159 - <== Total: 1
        com.rangers.entity.User{id=1, name='rangers', address='杭州'}
        14:49:39,497 DEBUG JdbcTransaction:123 - Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@206a70ef]
        14:49:39,499 DEBUG JdbcTransaction:91 - Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@206a70ef]
        14:49:39,500 DEBUG PooledDataSource:363 - Returned connection 543846639 to pool.
        14:49:39,500 DEBUG JdbcTransaction:123 - Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@7bedc48a]
        14:49:39,502 DEBUG JdbcTransaction:91 - Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@7bedc48a]
        14:49:39,502 DEBUG PooledDataSource:363 - Returned connection 2079179914 to pool.
      • 更新提交事务,与一级缓存一样,增删改操作提交事务会清空缓存

        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); User param = new User();
        param.setId(1); SqlSession sqlSession1 = sqlSessionFactory.openSession();
        IUserDao userDao1 = sqlSession1.getMapper(IUserDao.class);
        User user1 = userDao1.findOne(param);
        System.out.println("sqlSession1查询结果:"+user1);
        sqlSession1.close(); SqlSession sqlSession2 = sqlSessionFactory.openSession();
        IUserDao userDao2 = sqlSession2.getMapper(IUserDao.class);
        param.setName("游骑兵");
        param.setAddress("西安");
        Boolean flag = userDao2.updateUser(param) > 0;
        System.out.println("执行更新操作结果:"+flag);
        sqlSession2.commit();
        sqlSession2.close(); SqlSession sqlSession3 = sqlSessionFactory.openSession();
        IUserDao userDao3 = sqlSession3.getMapper(IUserDao.class);
        User user3 = userDao3.findOne(param);
        sqlSession3.close();
        System.out.println("sqlSession3查询结果:"+user3);

        查看控制台输出,经过sqlSession2提交事务后,sqlSession3的查询缓存命中率为0.0

        15:00:33,901 DEBUG IUserDao:62 - Cache Hit Ratio [com.rangers.dao.IUserDao]: 0.0
        15:00:33,904 DEBUG JdbcTransaction:137 - Opening JDBC Connection
        15:00:34,263 DEBUG PooledDataSource:406 - Created connection 543846639.
        15:00:34,263 DEBUG JdbcTransaction:101 - Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@206a70ef]
        15:00:34,267 DEBUG findOne:159 - ==> Preparing: select * from user where id=?
        15:00:34,290 DEBUG findOne:159 - ==> Parameters: 1(Integer)
        15:00:34,314 DEBUG findOne:159 - <== Total: 1
        sqlSession1查询结果:com.rangers.entity.User{id=1, name='rangers', address='杭州'}
        15:00:34,317 DEBUG JdbcTransaction:123 - Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@206a70ef]
        15:00:34,321 DEBUG JdbcTransaction:91 - Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@206a70ef]
        15:00:34,321 DEBUG PooledDataSource:363 - Returned connection 543846639 to pool.
        15:00:34,321 DEBUG JdbcTransaction:137 - Opening JDBC Connection
        15:00:34,322 DEBUG PooledDataSource:398 - Checked out connection 543846639 from pool.
        15:00:34,322 DEBUG JdbcTransaction:101 - Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@206a70ef]
        15:00:34,325 DEBUG updateUser:159 - ==> Preparing: update user set name=?,address=? where id=?
        15:00:34,325 DEBUG updateUser:159 - ==> Parameters: 游骑兵(String), 西安(String), 1(Integer)
        15:00:34,334 DEBUG updateUser:159 - <== Updates: 1
        执行更新操作结果:true
        15:00:34,335 DEBUG JdbcTransaction:70 - Committing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@206a70ef]
        15:00:34,445 DEBUG JdbcTransaction:123 - Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@206a70ef]
        15:00:34,448 DEBUG JdbcTransaction:91 - Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@206a70ef]
        15:00:34,450 DEBUG PooledDataSource:363 - Returned connection 543846639 to pool.
        15:00:34,450 DEBUG IUserDao:62 - Cache Hit Ratio [com.rangers.dao.IUserDao]: 0.0
        15:00:34,450 DEBUG JdbcTransaction:137 - Opening JDBC Connection
        15:00:34,451 DEBUG PooledDataSource:398 - Checked out connection 543846639 from pool.
        15:00:34,451 DEBUG JdbcTransaction:101 - Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@206a70ef]
        15:00:34,453 DEBUG findOne:159 - ==> Preparing: select * from user where id=?
        15:00:34,454 DEBUG findOne:159 - ==> Parameters: 1(Integer)
        15:00:34,458 DEBUG findOne:159 - <== Total: 1
        15:00:34,458 DEBUG JdbcTransaction:123 - Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@206a70ef]
        15:00:34,461 DEBUG JdbcTransaction:91 - Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@206a70ef]
        15:00:34,462 DEBUG PooledDataSource:363 - Returned connection 543846639 to pool.
        sqlSession3查询结果:com.rangers.entity.User{id=1, name='游骑兵', address='西安'}
    • 多表操作时,对MyBatis二级缓存的影响

      1. 问题:未同一namespace下进行增删改提交操作时,其他namespace的缓存是无法感知的

      例如:两个Mapper文件,AMapper.xml和BMapper.xml,B修改了user表中的内容,A是感知不到的,那么再从A里查询如果用到了缓存,就是旧的数据。

      ​ 新增UserMapper1.xml ,修改命名空间为com.rangers.dao.IUserDao1

      InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
      SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); User param = new User();
      param.setId(1); SqlSession sqlSession1 = sqlSessionFactory.openSession();
      IUserDao userDao1 = sqlSession1.getMapper(IUserDao.class);
      User user1 = userDao1.findOne(param);
      System.out.println("sqlSession1查询结果:"+user1);
      sqlSession1.close(); SqlSession sqlSession2 = sqlSessionFactory.openSession();
      param.setName("游骑兵");
      param.setAddress("西安");
      Boolean flag = sqlSession2.update("com.rangers.dao.IUserDao1.updateUser",param) > 0;
      System.out.println("执行更新操作结果:"+flag);
      sqlSession2.commit();
      sqlSession2.close(); SqlSession sqlSession3 = sqlSessionFactory.openSession();
      IUserDao userDao3 = sqlSession3.getMapper(IUserDao.class);
      User user3 = userDao3.findOne(param);
      sqlSession3.close();
      System.out.println("sqlSession3查询结果:"+user3);

      ​ 查看控制台输出,发现sqlSession2成功更新用户信息后,sqlSession3进行查询时二级缓存命中,依旧是sqlSession1中的结果,查询结果错误

      15:33:54,792 DEBUG JdbcTransaction:137 - Opening JDBC Connection
      15:33:55,164 DEBUG PooledDataSource:406 - Created connection 1165303897.
      15:33:55,165 DEBUG JdbcTransaction:101 - Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@45752059]
      15:33:55,168 DEBUG findOne:159 - ==> Preparing: select * from user where id=?
      15:33:55,186 DEBUG findOne:159 - ==> Parameters: 1(Integer)
      15:33:55,212 DEBUG findOne:159 - <== Total: 1
      sqlSession1查询结果:com.rangers.entity.User{id=1, name='Rangers', address='杭州'}
      15:33:55,215 DEBUG JdbcTransaction:123 - Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@45752059]
      15:33:55,218 DEBUG JdbcTransaction:91 - Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@45752059]
      15:33:55,218 DEBUG PooledDataSource:363 - Returned connection 1165303897 to pool.
      15:33:55,219 DEBUG JdbcTransaction:137 - Opening JDBC Connection
      15:33:55,220 DEBUG PooledDataSource:398 - Checked out connection 1165303897 from pool.
      15:33:55,220 DEBUG JdbcTransaction:101 - Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@45752059]
      15:33:55,224 DEBUG updateUser:159 - ==> Preparing: update user set name=?,address=? where id=?
      15:33:55,225 DEBUG updateUser:159 - ==> Parameters: 游骑兵(String), 西安(String), 1(Integer)
      15:33:55,233 DEBUG updateUser:159 - <== Updates: 1
      执行更新操作结果:true
      15:33:55,233 DEBUG JdbcTransaction:70 - Committing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@45752059]
      15:33:55,351 DEBUG JdbcTransaction:123 - Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@45752059]
      15:33:55,354 DEBUG JdbcTransaction:91 - Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@45752059]
      15:33:55,355 DEBUG PooledDataSource:363 - Returned connection 1165303897 to pool.
      15:33:55,357 DEBUG IUserDao:62 - Cache Hit Ratio [com.rangers.dao.IUserDao]: 0.5
      sqlSession3查询结果:com.rangers.entity.User{id=1, name='Rangers', address='杭州'}
      1. 解决

        在查询的Mapper文件中引入cache-ref标签,指向执行增删改操作表的命名空间,例如在UserMapper.xml中增加一下标签

        <cache-ref namespace="com.rangers.dao.IUserDao1"/>

        在此执行,查看控制台输出,发现第三次查询已直接从数据库中进行查询,结果正确

        15:46:05,486 DEBUG IUserDao1:62 - Cache Hit Ratio [com.rangers.dao.IUserDao1]: 0.0
        15:46:05,489 DEBUG JdbcTransaction:137 - Opening JDBC Connection
        15:46:05,788 DEBUG PooledDataSource:406 - Created connection 1165303897.
        15:46:05,789 DEBUG JdbcTransaction:101 - Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@45752059]
        15:46:05,793 DEBUG findOne:159 - ==> Preparing: select * from user where id=?
        15:46:05,822 DEBUG findOne:159 - ==> Parameters: 1(Integer)
        15:46:05,842 DEBUG findOne:159 - <== Total: 1
        sqlSession1查询结果:com.rangers.entity.User{id=1, name='rangers', address='杭州'}
        15:46:05,845 DEBUG JdbcTransaction:123 - Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@45752059]
        15:46:05,848 DEBUG JdbcTransaction:91 - Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@45752059]
        15:46:05,848 DEBUG PooledDataSource:363 - Returned connection 1165303897 to pool.
        15:46:05,849 DEBUG JdbcTransaction:137 - Opening JDBC Connection
        15:46:05,849 DEBUG PooledDataSource:398 - Checked out connection 1165303897 from pool.
        15:46:05,849 DEBUG JdbcTransaction:101 - Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@45752059]
        15:46:05,852 DEBUG updateUser:159 - ==> Preparing: update user set name=?,address=? where id=?
        15:46:05,852 DEBUG updateUser:159 - ==> Parameters: 游骑兵(String), 西安(String), 1(Integer)
        15:46:05,865 DEBUG updateUser:159 - <== Updates: 1
        执行更新操作结果:true
        15:46:05,865 DEBUG JdbcTransaction:70 - Committing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@45752059]
        15:46:05,970 DEBUG JdbcTransaction:123 - Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@45752059]
        15:46:05,974 DEBUG JdbcTransaction:91 - Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@45752059]
        15:46:05,976 DEBUG PooledDataSource:363 - Returned connection 1165303897 to pool.
        15:46:05,976 DEBUG IUserDao1:62 - Cache Hit Ratio [com.rangers.dao.IUserDao1]: 0.0
        15:46:05,976 DEBUG JdbcTransaction:137 - Opening JDBC Connection
        15:46:05,976 DEBUG PooledDataSource:398 - Checked out connection 1165303897 from pool.
        15:46:05,976 DEBUG JdbcTransaction:101 - Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@45752059]
        15:46:05,979 DEBUG findOne:159 - ==> Preparing: select * from user where id=?
        15:46:05,979 DEBUG findOne:159 - ==> Parameters: 1(Integer)
        15:46:05,985 DEBUG findOne:159 - <== Total: 1
        15:46:05,985 DEBUG JdbcTransaction:123 - Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@45752059]
        15:46:05,989 DEBUG JdbcTransaction:91 - Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@45752059]
        15:46:05,990 DEBUG PooledDataSource:363 - Returned connection 1165303897 to pool.
        sqlSession3查询结果:com.rangers.entity.User{id=1, name='游骑兵', address='西安'}
    • 是否应该使用二级缓存

      二级缓存的注意事项:

      1. 缓存是以namespace为单位的,不同namespace下的操作互不影响。

      2. insert,update,delete操作会清空所在namespace下的全部缓存。

      3. 通常使用MyBatis Generator生成的代码中,都是各个表独立的,每个表都有自己的namespace。

      4. 多表操作一定不要使用二级缓存,因为多表操作进行更新操作,一定会产生脏数据。

        如果你遵守二级缓存的注意事项,那么你就可以使用二级缓存。

        如果不能使用多表操作,二级缓存不就可以用一级缓存来替换掉吗?而且二级缓存是表级缓存,开销大,没有一级缓存直接使用 HashMap 来存储的效率更高,所以二级缓存并不推荐使用。

    引用内容参考:https://www.cnblogs.com/cxuanBlog/p/11333021.html

MyBatis(七):MyBatis缓存详解(一级缓存/二级缓存)的更多相关文章

  1. 【mybatis源码学习】mybtias一级,二级缓存

    转载:https://www.cnblogs.com/ysocean/p/7342498.html mybatis 为我们提供了一级缓存和二级缓存,可以通过下图来理解: ①.一级缓存是SqlSessi ...

  2. SpringBoot+Mybatis一级缓存和二级缓存详解

    本文主要介绍在SpringBoot项目中如何使用Mybatis的一级.二级缓存,为了演示方便,本文的数据库采用H2内存数据库,数据库连接池默认使用SpringBoot2.X自带的hikariCP. 正 ...

  3. Mybatis一级、二级缓存

      Mybatis一级.二级缓存   一级缓存 首先做一个测试,创建一个mapper配置文件和mapper接口,我这里用了最简单的查询来演示. <mapper namespace="c ...

  4. 170214、mybatis一级和二级缓存

    mybatis一级缓存是指在内存中开辟一块区域,用来保存用户对数据库的操作信息(sql)和数据库返回的数据,如果下一次用户再执行相同的请求, 那么直接从内存中读数数据而不是从数据库读取. 其中数据的生 ...

  5. Hibernate缓存简介和对比、一级缓存、二级缓存详解

    一.hibernate缓存简介 缓存的范围分为3类:  1.事务范围(单Session即一级缓存)     事务范围的缓存只能被当前事务访问,每个事务都有各自的缓存,缓存内的数据通常采用相互关联的对象 ...

  6. Hibernate一级缓存和二级缓存详解

    (1)一级缓存 是Session级别的缓存,一个Session做了一个查询操作,它会把这个操作的结果放在一级缓存中,如果短时间内这个session(一定要同一个session)又做了同一个操作,那么h ...

  7. hibernate的一级缓存和二级缓存详解

    hibernate为我们提供了一级缓存和二级缓存,目的是为了减少应用程序对数据库的访问次数. 一级缓存: (1)所谓一级缓存就是session级别的缓存,当我们使用他的范围是当前的session,当s ...

  8. Mybatis SQL映射文件详解

    Mybatis SQL映射文件详解 mybatis除了有全局配置文件,还有映射文件,在映射文件中可以编写以下的顶级元素标签: cache – 该命名空间的缓存配置. cache-ref – 引用其它命 ...

  9. Mybatis系列全解(四):全网最全!Mybatis配置文件XML全貌详解

    封面:洛小汐 作者:潘潘 做大事和做小事的难度是一样的.两者都会消耗你的时间和精力,所以如果决心做事,就要做大事,要确保你的梦想值得追求,未来的收获可以配得上你的努力. 前言 上一篇文章 <My ...

随机推荐

  1. requests -- Python

    使用requests方法后,会返回一个response对象,其存储了服务器响应的内容:如下r表示get请求后的响应对象r = requests.get('http://hz.58.com/sale.s ...

  2. 实战交付一套dubbo微服务到k8s集群(5)之使用Jenkins进行持续构建交付dubo服务的提供者

    1.登录到jenkins,新建一个项目 2.新建流水线 3.设置保留的天数及份数 4.添加第一个参数:设置项目的名称 5.添加第二个参数:docker镜像名称 6.添加第三个参数:项目所在的git中央 ...

  3. μC/OS-III---I笔记12---任务管理

    任务管理任务切换应该算是UCOS最基本的部分,首先保存当前任务寄存器的内容到当前任务的堆栈:接着弹出即将进行的任务的堆栈内容到寄存器中然后就是按寄存器内容执行,这个过程成为上下文切换.任务堆栈在创建任 ...

  4. Google Chrome All In One

    Google Chrome All In One Chrome Experiments Chrome 测试版 Chrome 开发者版 Chrome Canary 版 chrome://welcome/ ...

  5. Ajax & JSONP 原理

    Ajax & JSONP 原理 AJAX不是JavaScript的规范,它只是一个哥们"发明"的缩写:Asynchronous JavaScript and XML,意思就 ...

  6. Promise nested then execute order All In One

    Promise nested then execute order All In One Promise nested then nested Promise not return new Promi ...

  7. RESTful 架构 && RESTful API

    RESTful 架构 && RESTful API REpresentational State Transfer (REST) 具象状态传输https://en.wikipedia. ...

  8. SwiftUI render WKWebView

    SwiftUI render WKWebView // // ContentView.swift // webview-app // // Created by 夏凌晨 on 2020/10/27. ...

  9. 验证销售部门的数据查看权限-脚本demo

    1 # coding:utf-8 2 ''' 3 @file: run_old.py 4 @author: jingsheng hong 5 @ide: PyCharm 6 @createTime: ...

  10. JDK源码阅读-DirectByteBuffer

    本文转载自JDK源码阅读-DirectByteBuffer 导语 在文章JDK源码阅读-ByteBuffer中,我们学习了ByteBuffer的设计.但是他是一个抽象类,真正的实现分为两类:HeapB ...