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语句,说明执行更新语句后一级缓存会被清空。