← 返回首页
Mybatis基础教程(十五)
发表时间:2022-03-10 20:29:39
一级缓存

1.一级缓存

Mybatis对缓存提供支持,在没有缓存配置情况下,默认开启了一级缓存,一级缓存只是相对于同一个SqlSession而言。所以在参数和SQL完全一样的情况下,我们使用同一个SqlSession对象调用一个Mapper方法,往往只执行一次SQL,因为使用SelSession第一次查询后,MyBatis会将其放在缓存中,以后再查询的时候,如果没有声明需要刷新,并且缓存没有超时的情况下,SqlSession都会取出当前缓存的数据,而不会再次发送SQL到数据库。

2.一级缓存生命周期

实例:

在第二章-单表的CRUD的案例基础上,实现使用logback测试一级缓存。

项目结构图如下:

在pom.xml添加logback依赖。

<!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-classic -->
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.2.10</version>
    <scope>test</scope>
</dependency>

<!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-core -->
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-core</artifactId>
    <version>1.2.10</version>
</dependency>

<!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-access -->
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-access</artifactId>
    <version>1.2.10</version>
</dependency>

在mybatis-config.xml中添加日志配置。

<settings>
   <!--设置启用数据库字段下划线映射到java对象的驼峰式命名属性,默认为false-->
   <!-- 配置打印 SQL log 的路径前缀 以及懒加载 -->
   <setting name="logPrefix" value="mybatis.sql."/>
   <!-- 打开延迟加载的全局开关 -->
   <setting name="lazyLoadingEnabled" value="true"/>
   <setting name="aggressiveLazyLoading" value="false"/>
   <setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>

在resouces下新建logback目录,在resources/logback目录下创建logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<included>
    <appender name="MyBatis" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_HOME}/logs/mybatis-sql.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <FileNamePattern>${LOG_HOME}/logs/mybatis-sql.log.%d{yyyy-MM-dd}</FileNamePattern>
            <maxHistory>30</maxHistory>
        </rollingPolicy>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>%thread|%d{yyyy-MM-dd HH:mm:ss.SSS}|%level|%logger{36}|%m%n</pattern>
        </encoder>
    </appender>

    <logger name="mybatis.sql" level="DEBUG">
        <appender-ref ref="MyBatis"/>
    </logger>
</included>

创建测试用例。

    @Test
    public void testFirstLevelCache(){
        SqlSession session = null;
        Users u = null;
        try {
            session = SqlSessionFactoryUtil.openSqlSession();
            u = session.selectOne("getUser", 3);
            System.out.println(u);

            u = session.selectOne("getUser", 3);
            System.out.println(u);

        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            if (session != null) {
                session.close();
            }
        }
    }

运行结果:

20:31:18.505 [main] DEBUG mybatis.sql.com.mapper.usersMapper.getUser - ==>  Preparing: select * from users where uid=?
20:31:18.553 [main] DEBUG mybatis.sql.com.mapper.usersMapper.getUser - ==> Parameters: 3(Integer)
20:31:18.599 [main] DEBUG mybatis.sql.com.mapper.usersMapper.getUser - <==      Total: 1
Users(uid=3, username=宝宝, password=123456, mobile=15991167345, email=403353606@qq.com, type=admin)
Users(uid=3, username=宝宝, password=123456, mobile=15991167345, email=403353606@qq.com, type=admin)

我们发现仅仅执第一次查询执行了select语句。说明第二次查询使用了一级缓存。

第一次查询后更新用户资料。

    @Test
    public void testFirstLevelCache(){
        SqlSession session = null;
        Users u = null;
        try {
            session = SqlSessionFactoryUtil.openSqlSession();
            u = session.selectOne("getUser", 3);
            System.out.println(u);

            u.setPassword("123456");
            session.update("updateUser",u);
            session.commit();

            u = session.selectOne("getUser", 3);
            System.out.println(u);

        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            if (session != null) {
                session.close();
            }
        }
    }

运行结果:

20:33:55.634 [main] DEBUG mybatis.sql.com.mapper.usersMapper.getUser - ==>  Preparing: select * from users where uid=?
20:33:55.673 [main] DEBUG mybatis.sql.com.mapper.usersMapper.getUser - ==> Parameters: 3(Integer)
20:33:55.702 [main] DEBUG mybatis.sql.com.mapper.usersMapper.getUser - <==      Total: 1
Users(uid=3, username=宝宝, password=123456, mobile=15991167345, email=403353606@qq.com, type=admin)
20:33:55.704 [main] DEBUG mybatis.sql.com.mapper.usersMapper.updateUser - ==>  Preparing: update users set username = ?,password=? where uid = ?
20:33:55.706 [main] DEBUG mybatis.sql.com.mapper.usersMapper.updateUser - ==> Parameters: 宝宝(String), 123456(String), 3(Integer)
20:33:55.707 [main] DEBUG mybatis.sql.com.mapper.usersMapper.updateUser - <==    Updates: 1
20:33:55.707 [main] DEBUG org.apache.ibatis.transaction.jdbc.JdbcTransaction - Committing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@2d6c53fc]
20:33:55.708 [main] DEBUG mybatis.sql.com.mapper.usersMapper.getUser - ==>  Preparing: select * from users where uid=?
20:33:55.708 [main] DEBUG mybatis.sql.com.mapper.usersMapper.getUser - ==> Parameters: 3(Integer)
20:33:55.709 [main] DEBUG mybatis.sql.com.mapper.usersMapper.getUser - <==      Total: 1
Users(uid=3, username=宝宝, password=123456, mobile=15991167345, email=403353606@qq.com, type=admin)

我们发现更新后的查询又执行了一次select语句,说明执行更新语句后一级缓存会被清空。