[华为云在线课程][MyBatis入门][五][MyBatis缓存][学习笔记]
1.MyBatis一级缓存
MyBatis一级缓存的作用域是同一个SqlSession,在同一个SqlSession中两次执行相同的sql语句,第一次执行完毕后将数据库中查询到的数据写到缓存(内存)中,第二次会从缓存中获取数据将不再从数据库查询,从而提高效率。
当一个SqlSession结束后该SqlSession中的一级缓存也就不存在了。MyBatis默认开启一级缓存。
package org.example.mybatis04.model;
public class User {
private Integer id;
private String username;
private String address;
public User() {
}
public User(Integer id, String username, String address) {
this.id = id;
this.username = username;
this.address = address;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", address='" + address + '\'' +
'}';
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
package org.example.mybatis04.mapper;
import org.example.mybatis04.model.User;
public interface UserMapper {
User getUserById(Integer id);
}
<mappers>
<mapper resource="org/example/mybatis04/mapper/UserMapper.xml"/>
</mappers>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/schema/mybatis-3-mapper.dtd">
<mapper namespace="org.example.mybatis04.mapper.UserMapper">
<select id="getUserById" resultType="org.example.mybatis04.model.User">
select * from user where id=#{id};
</select>
</mapper>
package org.example.mybatis04;
import org.apache.ibatis.session.SqlSession;
import org.example.mybatis04.mapper.UserMapper;
import org.example.mybatis04.model.User;
import org.example.mybatis04.utils.SqlSessionFactoryUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class UserMapperTest {
private SqlSession sqlSession;
@Before
public void before() {
sqlSession= SqlSessionFactoryUtils.getInstance().openSession();
}
@Test
public void getUserById() {
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User userById = userMapper.getUserById(1);
System.out.println(userById);
/*
<== Total: 1
User{id=1, username='aaaa', address='beijing'}
* */
}
@After
public void after() {
sqlSession.close();
}
}
[DEBUG] 2022-07-11 06:19:58,998[yyyy-MM-dd] method:org.apache.ibatis.transaction.jdbc.JdbcTransaction.openConnection(JdbcTransaction.java:137)
Opening JDBC Connection
[DEBUG] 2022-07-11 06:19:59,438[yyyy-MM-dd] method:org.apache.ibatis.datasource.pooled.PooledDataSource.popConnection(PooledDataSource.java:434)
Created connection 1491860739.
[DEBUG] 2022-07-11 06:19:59,438[yyyy-MM-dd] method:org.apache.ibatis.transaction.jdbc.JdbcTransaction.setDesiredAutoCommit(JdbcTransaction.java:101)
Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@58ebfd03]
[DEBUG] 2022-07-11 06:19:59,438[yyyy-MM-dd] method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:137)
==> Preparing: select * from user where id=?;
[DEBUG] 2022-07-11 06:19:59,463[yyyy-MM-dd] method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:137)
==> Parameters: 1(Integer)
[DEBUG] 2022-07-11 06:19:59,494[yyyy-MM-dd] method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:137)
<== Total: 1
User{id=1, username='aaaa', address='beijing'}
[DEBUG] 2022-07-11 06:19:59,503[yyyy-MM-dd] method:org.apache.ibatis.transaction.jdbc.JdbcTransaction.resetAutoCommit(JdbcTransaction.java:123)
Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@58ebfd03]
[DEBUG] 2022-07-11 06:19:59,503[yyyy-MM-dd] method:org.apache.ibatis.transaction.jdbc.JdbcTransaction.close(JdbcTransaction.java:91)
Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@58ebfd03]
@Test
public void getUserById() {
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User userById = userMapper.getUserById(1);
System.out.println("userById = " + userById);
System.out.println("################################");
User userById1 = userMapper.getUserById(2);
System.out.println("userById1 = " + userById1);
}
[DEBUG] 2022-07-11 07:16:11,537[yyyy-MM-dd] method:org.apache.ibatis.transaction.jdbc.JdbcTransaction.openConnection(JdbcTransaction.java:137)
Opening JDBC Connection
[DEBUG] 2022-07-11 07:16:11,952[yyyy-MM-dd] method:org.apache.ibatis.datasource.pooled.PooledDataSource.popConnection(PooledDataSource.java:434)
Created connection 1491860739.
[DEBUG] 2022-07-11 07:16:11,952[yyyy-MM-dd] method:org.apache.ibatis.transaction.jdbc.JdbcTransaction.setDesiredAutoCommit(JdbcTransaction.java:101)
Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@58ebfd03]
[DEBUG] 2022-07-11 07:16:11,957[yyyy-MM-dd] method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:137)
==> Preparing: select * from user where id=?;
[DEBUG] 2022-07-11 07:16:11,982[yyyy-MM-dd] method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:137)
==> Parameters: 1(Integer)
[DEBUG] 2022-07-11 07:16:12,002[yyyy-MM-dd] method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:137)
<== Total: 1
userById = User{id=1, username='aaaa', address='beijing'}
################################
[DEBUG] 2022-07-11 07:16:12,012[yyyy-MM-dd] method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:137)
==> Preparing: select * from user where id=?;
[DEBUG] 2022-07-11 07:16:12,012[yyyy-MM-dd] method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:137)
==> Parameters: 2(Integer)
[DEBUG] 2022-07-11 07:16:12,012[yyyy-MM-dd] method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:137)
<== Total: 1
userById1 = User{id=2, username='bb', address='shanghai'}
[DEBUG] 2022-07-11 07:16:12,017[yyyy-MM-dd] method:org.apache.ibatis.transaction.jdbc.JdbcTransaction.resetAutoCommit(JdbcTransaction.java:123)
Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@58ebfd03]
[DEBUG] 2022-07-11 07:16:12,017[yyyy-MM-dd] method:org.apache.ibatis.transaction.jdbc.JdbcTransaction.close(JdbcTransaction.java:91)
Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@58ebfd03]
@Test
public void getUserById() {
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User userById = userMapper.getUserById(1);
System.out.println("userById = " + userById);
System.out.println("################################");
User userById1 = userMapper.getUserById(1);
System.out.println("userById1 = " + userById1);
}
[DEBUG] 2022-07-11 07:18:40,977[yyyy-MM-dd] method:org.apache.ibatis.datasource.pooled.PooledDataSource.popConnection(PooledDataSource.java:434)
Created connection 1491860739.
[DEBUG] 2022-07-11 07:18:40,977[yyyy-MM-dd] method:org.apache.ibatis.transaction.jdbc.JdbcTransaction.setDesiredAutoCommit(JdbcTransaction.java:101)
Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@58ebfd03]
[DEBUG] 2022-07-11 07:18:40,977[yyyy-MM-dd] method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:137)
==> Preparing: select * from user where id=?;
[DEBUG] 2022-07-11 07:18:41,007[yyyy-MM-dd] method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:137)
==> Parameters: 1(Integer)
[DEBUG] 2022-07-11 07:18:41,042[yyyy-MM-dd] method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:137)
<== Total: 1
userById = User{id=1, username='aaaa', address='beijing'}
################################
userById1 = User{id=1, username='aaaa', address='beijing'}
[DEBUG] 2022-07-11 07:18:41,057[yyyy-MM-dd] method:org.apache.ibatis.transaction.jdbc.JdbcTransaction.resetAutoCommit(JdbcTransaction.java:123)
Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@58ebfd03]
[DEBUG] 2022-07-11 07:18:41,057[yyyy-MM-dd] method:org.apache.ibatis.transaction.jdbc.JdbcTransaction.close(JdbcTransaction.java:91)
Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@58ebfd03]
多次查询,只执行一次SQL。但要注意,如果开启了一个新的SqlSession,则新的SqlSession无法使用之前的缓存,必须是同一个SqlSession中,缓存才有效。
2.MyBatis二级缓存
MyBatis二级缓存是多个SqlSession共享的,其作用域是mapper的同一个namespace,不同的SqlSession两次执行相同namespace下的SQL语句且SQL中传递参数也相同即最终执行相同的SQL语句,第一次执行完毕将数据库中查询的数据写到缓存(内存),第二次会从缓存中获取数据将不再从数据库查询,从而提供查询效率。MyBatis默认没有开启二级缓存,需要在setting全局参数中配置开启二级缓存。
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
然后在UserMapper.xml文件中开启缓存
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/schema/mybatis-3-mapper.dtd">
<mapper namespace="org.example.mybatis04.mapper.UserMapper">
<cache/>
<select id="getUserById" resultType="org.example.mybatis04.model.User" useCache="true">
select * from user where id=#{id};
</select>
</mapper>
开启了二级缓存后,还需要将要缓存的实体类实现Serializable接口,为了将缓存数据取出执行反序列化操作,因为二级缓存数据存储可能在内存或者硬盘中,如果我们再取出这个缓存的话就需要反序列化。
package org.example.mybatis04.model;
import java.io.Serializable;
public class User implements Serializable{
private Integer id;
private String username;
private String address;
}
如果没有在实体类中实现Serializable接口的话就会报出以下错误:
org.apache.ibatis.cache.CacheException: Error serializing object. Cause: java.io.NotSerializableException: org.example.mybatis04.model.User
接下来我们测试二级缓存是否和SqlSession有关
@Test
public void getUserById2() {
SqlSession sqlSession1 = sqlSessionFactory.openSession();
SqlSession sqlSession2 = sqlSessionFactory.openSession();
UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);
UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);
//第一次查询有sql语句,并将查询的结果放入缓存中
User user1 = userMapper1.getUserById(1);
System.out.println(user1);
//第一次查询后关闭SqlSession,SqlSession关闭后就会清除一级缓存
sqlSession1.close();
//SqlSession关闭后执行第二次查询,发现这次依然没有sql语句
User user2 = userMapper2.getUserById(1);
System.out.println(user2);
sqlSession2.close();
}
输出结果:
[DEBUG] 2022-07-12 05:43:23,742[yyyy-MM-dd] method:org.apache.ibatis.cache.decorators.LoggingCache.getObject(LoggingCache.java:60)
Cache Hit Ratio [org.example.mybatis04.mapper.UserMapper]: 0.0
[DEBUG] 2022-07-12 05:43:23,745[yyyy-MM-dd] method:org.apache.ibatis.transaction.jdbc.JdbcTransaction.openConnection(JdbcTransaction.java:137)
Opening JDBC Connection
[DEBUG] 2022-07-12 05:43:24,201[yyyy-MM-dd] method:org.apache.ibatis.datasource.pooled.PooledDataSource.popConnection(PooledDataSource.java:434)
Created connection 664091267.
[DEBUG] 2022-07-12 05:43:24,201[yyyy-MM-dd] method:org.apache.ibatis.transaction.jdbc.JdbcTransaction.setDesiredAutoCommit(JdbcTransaction.java:101)
Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@27953a83]
[DEBUG] 2022-07-12 05:43:24,204[yyyy-MM-dd] method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:137)
==> Preparing: select * from user where id=?;
[DEBUG] 2022-07-12 05:43:24,230[yyyy-MM-dd] method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:137)
==> Parameters: 1(Integer)
[DEBUG] 2022-07-12 05:43:24,257[yyyy-MM-dd] method:org.apache.ibatis.logging.jdbc.BaseJdbcLogger.debug(BaseJdbcLogger.java:137)
<== Total: 1
User{id=1, username='aaaa', address='beijing'}
[DEBUG] 2022-07-12 05:43:24,270[yyyy-MM-dd] method:org.apache.ibatis.transaction.jdbc.JdbcTransaction.resetAutoCommit(JdbcTransaction.java:123)
Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@27953a83]
[DEBUG] 2022-07-12 05:43:24,270[yyyy-MM-dd] method:org.apache.ibatis.transaction.jdbc.JdbcTransaction.close(JdbcTransaction.java:91)
Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@27953a83]
[DEBUG] 2022-07-12 05:43:24,270[yyyy-MM-dd] method:org.apache.ibatis.datasource.pooled.PooledDataSource.pushConnection(PooledDataSource.java:391)
Returned connection 664091267 to pool.
[WARN ] 2022-07-12 05:43:24,271[yyyy-MM-dd] method:org.apache.ibatis.io.SerialFilterChecker.check(SerialFilterChecker.java:45)
As you are using functionality that deserializes object streams, it is recommended to define the JEP-290 serial filter. Please refer to https://docs.oracle.com/pls/topic/lookup?ctx=javase15&id=GUID-8296D8E8-2B93-4B9A-856E-0A65AF9B8C66
[DEBUG] 2022-07-12 05:43:24,273[yyyy-MM-dd] method:org.apache.ibatis.cache.decorators.LoggingCache.getObject(LoggingCache.java:60)
Cache Hit Ratio [org.example.mybatis04.mapper.UserMapper]: 0.5
User{id=1, username='aaaa', address='beijing'}
- 点赞
- 收藏
- 关注作者
评论(0)