MyBatis一级缓存、二级缓存

一、MyBatis一级缓存

MyBatis默认启动一级缓存,一级缓存是SqlSession级别的

注意:有两个因素会使一级缓存失效
  1.对SqlSession进行commit()操作(即对数据库进行了增、删、改操作)。数据库中的数据发生了改变,此时若再从内存中读取缓存的数据,则会读取到错误的数据信息,所以此时旧的一级缓存中的数据会清空,当用户下一次执行查询操作时,会重新从数据库中读取数据并放入一级缓存中
  2.关闭SqlSession。一级缓存的设计是每个sqlsession单独使用一个缓存空间,不同的sqlsession是不能互相访问数据的。当然,在SqlSession关闭后,其中数据自然被清空。由此可以看出,一级缓存是SqlSession级别的

 测试一:

第一次查询时ID为2,第二次ID为3,第三次查询时ID又为3,运行程序,通过log4j日志得知,获得了3个结果,但是ID为2的SQL语句只执行了一次,第二次ID为2的SQL语句与第一次相同,直接从缓存中获取结果,而没有再次执行id=2的SQL语句。

    SqlSession sqlSession1=DbUtil.getSqlSession();     //这里自己编写了一个DbUtil工具类,其下有一个getSqlSession()的静态方法,由SqlSessionFactory的openSession()方法获得并返回一个SqlSession对象
    UserMapper userMapper1=sqlSession1.getMapper(UserMapper.class);

  System.out.println(userMapper1.findUserById(2));  //findUserById(int id)是UserMapper接口中的方法

    System.out.println(userMapper1.findUserById(3));

  System.out.println(userMapper1.findUserById(2));  

 测试二:

    sqlSession1.close();/**一旦关闭了sqlSession1,开启一个新的sqlSession2,那么sqlSession1的一级缓存失效,相同的ID为2的查询语句本次也会执行,在日志记录中会看到执行了两次select*from users where user_id=2的语句**/
    SqlSession sqlSession2=DbUtil.getSqlSession();
    UserMapper userMapper2=sqlSession2.getMapper(UserMapper.class);
    System.out.println(userMapper2.findUserById(2));

二、MyBatis二级缓存

一级缓存的作用域仅限于一个sqlsession,而二级缓存的作用域是一个namespace。但并不是意味着同一个namespace创建的mapper可以互相读取缓存内容,

这里的原则是,如果开启了二级缓存,那么在关闭sqlsession后,会把该sqlsession一级缓存中的数据添加到namespace的二级缓存中

开启二级缓存的步骤:

1.打开二级缓存总开关
打开总开关,只需要在mybatis总配置文件中加入一行设置

<settings>
   <!--开启二级缓存-->
    <setting name="cacheEnabled" value="true"/>
</settings>

2.打开需要使用二级缓存的mapper的开关

在需要开启二级缓存的mapper.xml(比如UserMapper.xml)中加入cache标签

<cache/>

3.POJO序列化

让需要使用二级缓存的POJO类实现Serializable接口,如

public class User implements Serializable {
}

在开启二级缓存之后,再次执行之前测试中的代码,会发现即使sqlSession1.close()之后,再重新获得新的SqlSession sqlSession2=DbUtil.getSqlSession(),然后再次执行相同的SQL操作,查询ID为2的用户,如下:
 
   UserMapper userMapper2=sqlSession2.getMapper(UserMapper.class);
    System.out.println(userMapper2.findUserById(2));

最终会发现在日志记录中只执行了一次
select*from users where user_id=2的语句,证明二级缓存开启成功!

必须注意的是:
即使开启了二级缓存,不同的sqlsession之间的缓存数据也不是想互访就能互访的,必须等到sqlsession关闭了以后,才会把其一级缓存中的数据写入二级缓存
如果把之前的sqlSession1.close()注释掉,那么同样会执行两次select*from users where user_id=2的SQL语句,因为sqlSession1没有关闭,一级缓存中的数据并没写入二级缓存,
而sqlSession2又无法访问sqlSession1的一级缓存中的数据,所以会重新执行该查询语句。

posted @ 2016-08-11 21:20  skip_2_my_lou  阅读(1831)  评论(1编辑  收藏  举报