【一级缓存】
- MyBatis默认开启一级缓存,即:同一个SqlSession对象调用同一个Mapper的方法,如果没有声明需要刷新,并且缓存没超时的情况下,一般只执行一次SQL,其他的查询SqlSession都只会取出当前缓存的数据。如下所示:
- CacheExecuter.java
public class CacheExecuter {
public static void main(String[] args) {
SqlSession sqlSession = SqlSessionFactoryUtil.openSqlSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user1 = userMapper.getUserById(1L);
System.out.println("----真实查询-----user1 = " user1);
User user2 = userMapper.getUserById(1L);
System.out.println("----缓存查询-----user2 = " user2);
/**
* 开启了新的sqlSession,则无法利用一级缓存。因为一级缓存是sqlSession之间隔离的。
*/
sqlSession = SqlSessionFactoryUtil.openSqlSession();
userMapper = sqlSession.getMapper(UserMapper.class);
User user3 = userMapper.getUserById(1L);
System.out.println("----真实查询-----user3 = " user3);
}
}
输出如下:
代码语言:javascript复制Created connection 1071097621.
Returned connection 1071097621 to pool.
Cache Hit Ratio [mapper.UserMapper]: 0.0
Opening JDBC Connection
Checked out connection 1071097621 from pool.
Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@3fd7a715]
==> Preparing: select id, name, age from tb_user where id = ?
==> Parameters: 1(Long)
<== Columns: id, name, age
<== Row: 1, muse1, 22
<== Total: 1
----真实查询-----user1 = User{id=1, name='muse1', age=22, userContacts=null}
Cache Hit Ratio [mapper.UserMapper]: 0.0
----缓存查询-----user2 = User{id=1, name='muse1', age=22, userContacts=null}
Cache Hit Ratio [mapper.UserMapper]: 0.0
Opening JDBC Connection
Created connection 280265505.
Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@10b48321]
==> Preparing: select id, name, age from tb_user where id = ?
==> Parameters: 1(Long)
<== Columns: id, name, age
<== Row: 1, muse1, 22
<== Total: 1
----真实查询-----user3 = User{id=1, name='muse1', age=22, userContacts=null}
Process finished with exit code 0
【二级缓存】
- 在UserMapper.xml中添加<cache/>标签。
- sqlSession.commit(); 当使用二级缓存的时候,只有调用了commit方法后才会生效。
- POJO必须实现Serializable接口。
实现如下所示:
- UserMapper.xml
<cache/>
- User.java
public class User implements Serializable
- CacheExecuter.java
public class CacheExecuter {
public static void main(String[] args) {
SqlSession sqlSession = SqlSessionFactoryUtil.openSqlSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user1 = userMapper.getUserById(1L);
System.out.println("----真实查询-----user1 = " user1);
//当使用二级缓存的时候,只有调用了commit方法后才会生效。
sqlSession.commit();
User user2 = userMapper.getUserById(1L);
System.out.println("----缓存查询-----user2 = " user2);
/**
* 开启了新的sqlSession,则无法利用一级缓存。因为一级缓存是sqlSession之间隔离的。
*/
sqlSession = SqlSessionFactoryUtil.openSqlSession();
userMapper = sqlSession.getMapper(UserMapper.class);
User user3 = userMapper.getUserById(1L);
System.out.println("----缓存查询-----user3 = " user3);
}
}
输入如下:
代码语言:javascript复制Created connection 1071097621.
Returned connection 1071097621 to pool.
Cache Hit Ratio [mapper.UserMapper]: 0.0
Opening JDBC Connection
Checked out connection 1071097621 from pool.
Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@3fd7a715]
==> Preparing: select id, name, age from tb_user where id = ?
==> Parameters: 1(Long)
<== Columns: id, name, age
<== Row: 1, muse1, 22
<== Total: 1
----真实查询-----user1 = User{id=1, name='muse1', age=22, userContacts=null}
Cache Hit Ratio [mapper.UserMapper]: 0.5
----缓存查询-----user2 = User{id=1, name='muse1', age=22, userContacts=null}
Cache Hit Ratio [mapper.UserMapper]: 0.6666666666666666
----缓存查询-----user3 = User{id=1, name='muse1', age=22, userContacts=null}
- 配置缓存参数UserMapper.xml
<cache eviction="LRU" flushInterval="1000" size="1000" readOnly="true"/>
【参数解释】
eviction:缓存回收策略:
- LRU:最近最少使用,移除最长时间不用的对象。
- FIFO:先进先出,按对象进入缓存的顺序来移除它们。
- SOFT:软引用,移除基于垃圾回收器状态和软引用规则的对象。
- WEAK:弱引用,移除最长时间不用的对象。
flushInterval:刷新间隔时间,单位为毫秒。如果不配置,那么当SQL被执行的时候才会去刷新缓存。
size:引用数据,正整数,代表缓存最多可以存储多少个对象,不宜设置过大。否则会内存溢出。
readOnly:只读。