mybatis进阶(8)--查询缓存之二级缓存

话不多说看图:
这里写图片描述

上节中提到,二级缓存是mapper级别的。可以跨sqlSession使用。

过程分析:

首先我们需要手动开启mybatis的二级缓存
sqlSession1发起查询用户id为1的用户信息,先去缓存中后是否有id为1的用户信息,如果没有,从数据库查询用户信息,并将用户信息存储到二级缓存中去
如果sqlSession3去执行相同mapper下的commit操作(插入,更新,删除),清空sqlSession的二级缓存
sqlSession2发起查询用户id为1的用户信息,先去缓存中后是否有id为1的用户信息,缓存中有,直接从缓存中获取用户信息。

二级缓存和一级缓存的区别:

二级缓存的范围更大,多个sqlSession共享一个userMapper的二级缓存
userMapper有一个二级缓存区域(按namespace分),其他的mapper也有自己的二级缓存区域
每个namespace的mapper都有一个二级缓存区域,两个mapper的namespace如果相同,那么这两个mapper执行sql查询将数据存在相同的二级缓存中去

1.开启二级缓存:
二级缓存是mapper范围级别,除了在sqlMapConfig.xml中配置二级缓存开关,还需要在具体的mapper.xml中开启二级缓存
在sqlMapConfig.xml中的settings中配置

<settings>
        <!-- 打开延迟加载开关 -->
        <setting name="lazyLoadingEnabled" value="true"/>
        <!-- 将积极加载改变成消极加载,也就是需要时加载 -->
        <setting name="aggressiveLazyLoading" value="false"/>
        <!-- 开启二级缓存 -->
        <setting name="cacheEnabled" value="true"/>
    </settings>

在userMapper.xml中开启二级缓存,它里面的sql执行完会存储到它的缓存区域(hashmap)中

<!-- 开启本mapper的namespace下的二级缓存 -->
    <cache></cache>

2.调用pojo类的实现序列化接口

public class User implements Serializable{...}

为了将缓存数据去除执行反序列化,因为为二级缓存数据存储介质不一样
3.测试二级缓存

先来测试下两次请求查询的执行结果

// 测试二级缓存
    @Test
    public void testCache2() throws Exception {
        SqlSession sqlSession1 = sqlSessionFactory.openSession();
        SqlSession sqlSession2 = sqlSessionFactory.openSession();
        SqlSession sqlSession3 = sqlSessionFactory.openSession();

        // 获取代理对象
        UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);
        // 使用sqlSession1
        // 第一次发起请求查询用户id为1的用户
        User u = userMapper1.findUserById(1);
        System.out.println(u);

        // 这里执行关闭操作,将sqlSession1中的数据写到二级缓存
        sqlSession1.close();

        UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);
        // 使用sqlSession2
        // 第2次发起请求查询用户id为1的用户
        User u2 = userMapper2.findUserById(1);
        System.out.println(u2);

        sqlSession2.close();


    }

执行结果:

Cache Hit Ratio [com.ddd.mybatis.mapper.UserMapper]: 0.0
2017-07-19 08:54:19,761 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Opening JDBC Connection
2017-07-19 08:54:20,006 [main] [org.apache.ibatis.datasource.pooled.PooledDataSource]-[DEBUG] Created connection 762493988.
2017-07-19 08:54:20,006 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@2d72bc24]
2017-07-19 08:54:20,008 [main] [com.ddd.mybatis.mapper.UserMapper.findUserById]-[DEBUG] ==>  Preparing: SELECT * FROM USER WHERE id=? 
2017-07-19 08:54:20,074 [main] [com.ddd.mybatis.mapper.UserMapper.findUserById]-[DEBUG] ==> Parameters: 1(Integer)
2017-07-19 08:54:20,100 [main] [com.ddd.mybatis.mapper.UserMapper.findUserById]-[DEBUG] <==      Total: 1
User [id=1, username=林更新, sex=男, birthday=Tue Jul 18 00:00:00 CST 2017, address=北京市海淀区, ordersList=null]
2017-07-19 08:54:20,111 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@2d72bc24]
2017-07-19 08:54:20,112 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@2d72bc24]
2017-07-19 08:54:20,113 [main] [org.apache.ibatis.datasource.pooled.PooledDataSource]-[DEBUG] Returned connection 762493988 to pool.
2017-07-19 08:54:20,134 [main] [com.ddd.mybatis.mapper.UserMapper]-[DEBUG] Cache Hit Ratio [com.ddd.mybatis.mapper.UserMapper]: 0.5
User [id=1, username=林更新, sex=男, birthday=Tue Jul 18 00:00:00 CST 2017, address=北京市海淀区, ordersList=null]

可以看出来,Cache Hit Ratio [com.ddd.mybatis.mapper.UserMapper]: 0.0表示缓存命中率为0,因为第一次在缓存中没有找到,所以去数据库中找,发出了sql语句,第二次找就直接在缓存中找,然后命中,两次找到一次,所以命中率为0.5

再来测试3个有查询有提交的:

// 测试二级缓存
    @Test
    public void testCache2() throws Exception {
        SqlSession sqlSession1 = sqlSessionFactory.openSession();
        SqlSession sqlSession2 = sqlSessionFactory.openSession();
        SqlSession sqlSession3 = sqlSessionFactory.openSession();

        // 获取代理对象
        UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);
        // 使用sqlSession1
        // 第一次发起请求查询用户id为1的用户
        User u = userMapper1.findUserById(1);
        System.out.println(u);

        // 这里执行关闭操作,将sqlSession1中的数据写到二级缓存
        sqlSession1.close();

        // 获取代理对象
        UserMapper userMapper3 = sqlSession3.getMapper(UserMapper.class);
        // 使用sqlSession3
        // 第2次发起请求查询用户id为1的用户
        User u3 = userMapper3.findUserById(1);
        u3.setUsername("王思聪");
        userMapper3.updateUser(u3);
        sqlSession3.commit();
        System.out.println(u3);

        // 这里执行关闭操作,将sqlSession3中的数据写到二级缓存
        sqlSession3.close();

        UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);
        // 使用sqlSession2
        // 第3次发起请求查询用户id为1的用户
        User u2 = userMapper2.findUserById(1);

        System.out.println(u2);

        sqlSession2.close();

    }
Cache Hit Ratio [com.ddd.mybatis.mapper.UserMapper]: 0.0
2017-07-19 09:01:15,731 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Opening JDBC Connection
2017-07-19 09:01:15,983 [main] [org.apache.ibatis.datasource.pooled.PooledDataSource]-[DEBUG] Created connection 1019014919.
2017-07-19 09:01:15,983 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@3cbcef07]
2017-07-19 09:01:15,986 [main] [com.ddd.mybatis.mapper.UserMapper.findUserById]-[DEBUG] ==>  Preparing: SELECT * FROM USER WHERE id=? 
2017-07-19 09:01:16,042 [main] [com.ddd.mybatis.mapper.UserMapper.findUserById]-[DEBUG] ==> Parameters: 1(Integer)
2017-07-19 09:01:16,064 [main] [com.ddd.mybatis.mapper.UserMapper.findUserById]-[DEBUG] <==      Total: 1
User [id=1, username=林更新, sex=男, birthday=Tue Jul 18 00:00:00 CST 2017, address=北京市海淀区, ordersList=null]
2017-07-19 09:01:16,072 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@3cbcef07]
2017-07-19 09:01:16,072 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@3cbcef07]
2017-07-19 09:01:16,072 [main] [org.apache.ibatis.datasource.pooled.PooledDataSource]-[DEBUG] Returned connection 1019014919 to pool.
2017-07-19 09:01:16,075 [main] [com.ddd.mybatis.mapper.UserMapper]-[DEBUG] Cache Hit Ratio [com.ddd.mybatis.mapper.UserMapper]: 0.5
2017-07-19 09:01:16,075 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Opening JDBC Connection
2017-07-19 09:01:16,075 [main] [org.apache.ibatis.datasource.pooled.PooledDataSource]-[DEBUG] Checked out connection 1019014919 from pool.
2017-07-19 09:01:16,076 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@3cbcef07]
2017-07-19 09:01:16,076 [main] [com.ddd.mybatis.mapper.UserMapper.updateUser]-[DEBUG] ==>  Preparing: UPDATE USER SET username=?,birthday=?,sex=?,address=? WHERE id=? 
2017-07-19 09:01:16,079 [main] [com.ddd.mybatis.mapper.UserMapper.updateUser]-[DEBUG] ==> Parameters: 王思聪(String), 2017-07-18 00:00:00.0(Timestamp), 男(String), 北京市海淀区(String), 1(Integer)
2017-07-19 09:01:16,080 [main] [com.ddd.mybatis.mapper.UserMapper.updateUser]-[DEBUG] <==    Updates: 1
2017-07-19 09:01:16,080 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Committing JDBC Connection [com.mysql.jdbc.JDBC4Connection@3cbcef07]
User [id=1, username=王思聪, sex=男, birthday=Tue Jul 18 00:00:00 CST 2017, address=北京市海淀区, ordersList=null]
2017-07-19 09:01:16,140 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@3cbcef07]
2017-07-19 09:01:16,141 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@3cbcef07]
2017-07-19 09:01:16,141 [main] [org.apache.ibatis.datasource.pooled.PooledDataSource]-[DEBUG] Returned connection 1019014919 to pool.
2017-07-19 09:01:16,141 [main] [com.ddd.mybatis.mapper.UserMapper]-[DEBUG] Cache Hit Ratio [com.ddd.mybatis.mapper.UserMapper]: 0.3333333333333333
2017-07-19 09:01:16,141 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Opening JDBC Connection
2017-07-19 09:01:16,141 [main] [org.apache.ibatis.datasource.pooled.PooledDataSource]-[DEBUG] Checked out connection 1019014919 from pool.
2017-07-19 09:01:16,142 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@3cbcef07]
2017-07-19 09:01:16,142 [main] [com.ddd.mybatis.mapper.UserMapper.findUserById]-[DEBUG] ==>  Preparing: SELECT * FROM USER WHERE id=? 
2017-07-19 09:01:16,143 [main] [com.ddd.mybatis.mapper.UserMapper.findUserById]-[DEBUG] ==> Parameters: 1(Integer)
2017-07-19 09:01:16,145 [main] [com.ddd.mybatis.mapper.UserMapper.findUserById]-[DEBUG] <==      Total: 1
User [id=1, username=王思聪, sex=男, birthday=Tue Jul 18 00:00:00 CST 2017, address=北京市海淀区, ordersList=null]

当sqlSession3提交后,将会清空二级缓存,下次查将查最新的数据,所以第三次查询会发出sql代码

4.禁用二级缓存
在statement中设置useCache=”false”将会禁用二级缓存,每次查询都会发出sql去查询,默认是true,即该sql使用二级缓存

应用场合:针对每次查询都需要最新数据sql,要设置禁用二级缓存

5.刷新缓存(就是清空缓存)
在同一namespace下的mapper中,如果有增删改操作后需要刷新缓存,避免脏读

在statement中设置flushCache=”false”将会不刷新缓存,他默认是true。如果设置为false,在我们手动更改数据库中的查询数据会出现脏读

一般执行完commit操作都要执行刷新缓存,防止脏读数据。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值