MyBatis缓存
什么是MyBatis缓存
使用缓存可以减少java应用与数据库的交互次数,从而提升程序的运行效率。
例如查询出 id = 1 的对象,第一次查询出来之后会自动将该对象保存到缓存中,当下一次查询的时候,直接从级缓存中取出该对象即可,无需再次访问数据库。
MyBatis缓存分类
一级缓存:SqlSession 级别,默认开启,并且不能关闭。
操作数据库时需要创建 SqlSession 对象,在对象中有一个 HashMap 用于存储缓存数据,不同的 SqlSession 之间的缓存数据区域是互不影响的。
一级缓存的作用域是 SqlSession 范围的,当在 同一个 SqlSession 中执行两次相同的 SQL 语句时,第一次执行完毕会将结果保存到缓存中,第二次查询时直接从缓存中获取。
需要注意的是,如果 SqlSession 执行了 DML 操作(insert、update、delete),MyBatis 必须将缓存清空,以保证数据的准确性
代码
package com.mybatistest.test;
import com.mybatistest.entity.Account;
import com.mybatistest.repository.AccountRepository;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.InputStream;
public class Test4 {
public static void main(String[] args) {
//加载MyBatis配置文件
InputStream inputStream = Test4.class.getClassLoader().getResourceAsStream("config.xml");
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
AccountRepository accountRepository = sqlSession.getMapper(AccountRepository.class);
Account account = accountRepository.findById(1L);
System.out.println(account);
sqlSession.close();
sqlSession = sqlSessionFactory.openSession();
accountRepository = sqlSession.getMapper(AccountRepository.class);
Account account1 = accountRepository.findById(1L);
System.out.println(account1);
}
}
二级缓存:Mapper 级别,默认关闭,可以开启。
使用二级缓存时,多个 SqlSession 使用同一个 Mapper 的 SQL 语句操作数据库,得到的数据会存在二级缓存区,同样是使用 HashMap 进行数据存储,相比较于一级缓存,二级缓存范围更大,多个 SqlSession 可以共用二级缓存,二级缓存是跨 SqlSession 的。
二级缓存是多个 SqlSession 共享的,其作用域是 Mapper 的同一个 namespace ,不同的 SqlSession 两次执行相同的 namespace 下的 SQL 语句,参数也相等,则第一次执行成功之后会将数据保存到二级缓存中,第二次可直接从二级缓存中取出数据。
MyBatis 自带的二级缓存
-
在 config.xml 中配置开启二级缓存:在 settings 标签中添加:
<!-- 开启二级缓存 --> <setting name="cacheEnabled" value="true"/>
-
在对应的 Mapper.xml 中配置二级缓存: 在 mapper 标签中添加
<cache></cache>
-
在实体类中实现序列化接口
@Data @AllArgsConstructor @NoArgsConstructor public class Account implements Serializable { private long id; private String username; private String password; private int age; }
ehcache 二级缓存(第三方)
-
在 pom.xml 中添加相关依赖:
<!-- 二级缓存 --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-ehcache</artifactId> <version>1.0.0</version> </dependency> <dependency> <groupId>net.sf.ehcache</groupId> <artifactId>ehcache-core</artifactId> <version>2.4.3</version> </dependency>
-
添加 ehcache.xml
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd"> <diskStore/> <defaultCache maxElementsInMemory="100" maxElementsOnDisk="100000" eternal="false" overflowToDisk="false" timeToIdleSeconds="120" timeToLiveSeconds="120" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU"> </defaultCache> </ehcache>
-
在 config.xml 中配置开启二级缓存:在 settings 标签中添加:
<!-- 开启二级缓存 --> <setting name="cacheEnabled" value="true"/>
-
在 Mapper.xml 中配置二级缓存
<!-- ehcache二级缓存 --> <cache type="org.mybatis.caches.ehcache.EhcacheCache"> <!-- 缓存创建之后,最后一次访问缓存的时间至缓存失效的时间间隔 --> <property name="timeToIdleSeconds " value="3600"/> <!-- 缓存自创建起至缓存失效的时间间隔 --> <property name="timeToLiveSeconds" value="3600"/> <!-- 缓存的回收策略,LRU表示移除近期使用最少的对象 --> <property name="memoryStoreEvictionPolicy" value="LRU"/> </cache>
-
实体类不需要实现序列化接口
@Data @AllArgsConstructor @NoArgsConstructor public class Account { private long id; private String username; private String password; private int age; }