一级缓存和二级缓存问题

MyBatis的一级缓存是SqlSession级别,执行查询后结果存储于SqlSession,同一SqlSession内重复查询不会再次访问数据库。二级缓存是Mapper级别,多个SqlSession共享,需手动配置。flushCache属性用于清除缓存,useCache表示是否启用二级缓存。在使用缓存时需注意数据同步问题和缓存失效情况。
摘要由CSDN通过智能技术生成

介绍

MyBatis 中的缓存,主要分为一级缓存和二级缓存。

一级缓存是 SqlSession 级别的缓存,也叫本地缓存。当执行一个 SqlSession 的查询时,查询到的结果会被保存在 SqlSession 的缓存中。同一个 SqlSession 内执行相同的 SQL 语句,则会从缓存中获取数据,而不会再向数据库发出请求。一级缓存默认开启,不需要手动配置。

二级缓存是 Mapper 级别的缓存,也叫全局缓存。多个 SqlSession 共享一块缓存区域,从而减少了对数据库的访问次数。需要手动配置开启,在 Mapper.xml 文件中添加 <cache> 标签即可。

一般情况下,我们优先考虑使用一级缓存,因为它是自动开启的,可以避免一些可能的问题。如果在具体的场景中需要使用到二级缓存,可以单独配置。

需要注意的是,二级缓存虽然可以提升性能,但也带来了一些问题。如缓存的数据和数据库中的数据不一致等问题,因此在使用二级缓存时,需要谨慎处理缓存与数据库之间的数据同步问题。

如何关闭一次缓存,并开启二级缓存

Mybatis是Java语言中一种流行的持久化框架,主要用于关系型数据库操作。该框架通过映射配置文件将Java类映射到相应的数据库表中,并提供了一系列SQL执行的方法和优化机制。其中,flushCache和useCache是两个常见的缓存控制选项。

flushCache

flushCache是Mybatis提供的一个属性,当为true时,它会把该条SQL语句所在的缓存清除,这样可以在下次查询时不从缓存中读取,直接重新执行SQL语句查询数据库。

例如:

<select id="getUserById" parameterType="int" resultType="com.example.User" flushCache="true">
  select * from user where id = #{id}
</select>

上述示例,使用flushCache="true"代表需要刷新缓存,在每次调用getUserById查询语句时都会清空缓存从而重新执行SQL查询。

useCache

useCache是Mybatis提供的另一个属性,表示是否使用二级缓存,默认值为true。开启该属性后,Mybatis会先检查是否有缓存可用,如果有,则直接返回结果,否则才会执行SQL语句。

例如:

<select id="getUserById" parameterType="int" resultType="com.example.User" useCache="true">
  select * from user where id = #{id}
</select>

上述示例,使用useCache="true"声明需要使用二级缓存,在每次调用getUserById查询时,先从缓存中获取数据,如果没有命中再去查询数据库,查到数据之后会将其放入缓存。注意该特性只对一级缓存有效,如果要使用二级缓存,需配置相应的cache标签。

案例

查询代码测试

    @Test
    public void query(){
        SqlSession sqlSession= MyUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user1 = mapper.getById(1);
        System.out.println(user1);
        System.out.println("======================");
        User user2 = mapper.getById(1);
        System.out.println(user2);
        sqlSession.close();
    }

下面结果可以解释一级缓存默认开启,查询只查了一次

如果关闭了一级缓存,就需要查询两次,如图:

缓存失效的情况:

  • 查询不同的语句
  • 增删改操作,可能会改变原来的数据,所以必定会刷新缓存
  • 手动清理缓存

 查询和插入代码测试

    @Test
    public void query(){
        SqlSession sqlSession= MyUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user1 = mapper.getById(1);
        int i = mapper.addUser(new User(9, "jdasi", "21423"));
        if(i>0){
            System.out.println("插入成功");
        }
        System.out.println("======================");
        System.out.println(user1);
        sqlSession.close();
    }

当分别执行查询和插入,执行两次,此时缓存失效

如果需要开启二级缓存,在sql映射文件添加

<cache/>

如图:

如果遇到下面的问题

在需要在实体类实现一个序列化接口即可

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值