前面我们说了一级缓存,但是实际上我们说那玩意其实不咋实用。于是既然设计了缓存体系,就不可能弄个不实用的给人们。所以这里就引出二级全局缓存。
全局缓存就是无视sqlSession,你可以理解为一个分布式的缓存。作为全局的访问。
一、二级缓存
1、开启方式
二级缓存默认是不开启的,所以他需要你手动去开启。开启方式需要满足下面四个条件。
1、需要在核心配置文件,我的是sqlMapConfig.xml中指定,在<setting 中的配置。其实最新版mybatis这个条件其实可以不用,因为在configuration中的cache默认就是true。
2、需要在mapper.xml中引进二级缓存Cache的标签。
3、需要在查询标签<select中引入useCache属性打开。,其实这个也是可以不用配置的,我们这里就先配置上。
4、需要有事务的存在。
第一步和第三步可以不写。
于是我们就来操作验证一下,我们首先在UserMapper.xml中配置第二步和第三步。
<mapper namespace="com.yx.dao.IUserDao">
<cache></cache>
<select id="findAll" resultType="com.yx.domain.User" useCache="true">
SELECT * FROM `user`
</select>
</mapper>
然后在代码中开启事务的提交。
@Test
public void test3() throws IOException {
// 读取配置文件转化为流
InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = factory.openSession();
SqlSession sqlSession2 = factory.openSession();
//这⾥不调⽤SqlSession的api,⽽是获得了接⼝对象,调⽤接⼝中的⽅法。使用JDK动态代理产生代理对象
IUserDao userDao = sqlSession.getMapper(IUserDao.class);
IUserDao userDao2 = sqlSession2.getMapper(IUserDao.class);
// 第一次执行查询
List<User> userList = userDao.findAll();
userList.forEach(user -> {
System.out.println(user.toString());
});
// 事务提交
sqlSession.commit();
System.out.println("*************************************************");
// 第二次执行相同的查询
List<User> userList2 = userDao2.findAll();
userList2.forEach(user -> {
System.out.println(user.toString());
});
// 事务提交
sqlSession2.commit();
}
我们看下输出:
Opening JDBC Connection
Loading class `com.mysql.jdbc.Driver'. This is deprecated. The new driver class is `com.mysql.cj.jdbc.Driver'. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.
Created connection 203819996.
Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@c260bdc]
==> Preparing: SELECT * FROM `user`
==> Parameters:
<== Columns: id, name
<== Row: 1, 张飞
<== Row: 2, 关羽
<== Row: 3, 孙权
<== Total: 3
User{id=1, username='张飞'}
User{id=2, username='关羽'}
User{id=3, username='孙权'}
*************************************************
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
Cache Hit Ratio [com.yx.dao.IUserDao]: 0.5// 缓存命中
User{id=1, username='张飞'}
User{id=2, username='关羽'}
User{id=3, username='孙权'}
我们看到缓存被命中了,第二次新的sqlsession中并没有执行sql,也没有创建连接,可见mybat