MyBatis包含一个非常强大的查询缓存特性,它可以非常方便地定制和配置缓存。缓存可以极大的提升查询效率。
MyBatis系统中默认定义了两级缓存:一级缓存和二级缓存
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
<build>
<!--解决maven静态资源过滤的问题-->
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties
**/ *.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties
**/ *.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
<plugins>
<!-- 设置jdk的版本-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<!--核心配置文件-->
<configuration>
<!--引入外部配置文件,必须写在首行-->
<properties resource="db.properties"/>
<!--设置-->
<settings>
<!--设置日志实现-->
<setting name="logImpl" value="LOG4J"/>
<!--开启驼峰命名转换-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
<!--设置包名的方式设置别名-->
<typeAliases>
<package name="com.bao.pojo"/>
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/bao/dao/BlogMapper.xml"/>
</mappers>
</configuration>
package com.bao.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Blog {
private String id;
private String title;
private String author;
/*
* 1.建议使用util包下的date
* 2.属性名和字段名不一致,可通过设置mapUnderscoreToCamelCase的值为true,来开启自动驼峰命名规则映射
* */
private Date createTime;
private int views;
}
编写接口
package com.bao.dao;
import com.bao.pojo.Blog;
public interface BlogMapper {
/*查询一条数据*/
Blog getBlogById(@Param("id") int id);
}
编写映射文件
一级缓存也叫本地缓存:
@Test
public void testGetBlogById() {
SqlSession sqlSession = MybatisUtil.getSqlSession();
SqlSession sqlSession1 = MybatisUtil.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
BlogMapper mapper1 = sqlSession1.getMapper(BlogMapper.class);
Blog blogById = mapper.getBlogById(1);
Blog blogById1 = mapper1.getBlogById(1);
System.out.println(blogById);
System.out.println(blogById1);
}
测试代码
@Test
public void test1() {
SqlSession sqlSession = MybatisUtil.getSqlSession();
BlogMapper blogMapper = sqlSession.getMapper(BlogMapper.class);
Blog blogById = blogMapper.getBlogById(1);
System.out.println(blogById);
System.out.println("-----------");
int i = blogMapper.deleteBlog(2);
System.out.println(i);
Blog blogById1 = blogMapper.getBlogById(1);
System.out.println(blogById1);
sqlSession.close();
}
未使用sqlSession.clearCache()前,测试代码
@Test
public void test2() {
SqlSession sqlSession = MybatisUtil.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
Blog blogById = mapper.getBlogById(1);
// sqlSession.clearCache();
Blog blogById1 = mapper.getBlogById(1);
System.out.println(blogById);
System.out.println(blogById1);
sqlSession.close();
}
使用该方法后代码
@Test
public void test2() {
SqlSession sqlSession = MybatisUtil.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
Blog blogById = mapper.getBlogById(1);
sqlSession.clearCache();
Blog blogById1 = mapper.getBlogById(1);
System.out.println(blogById);
System.out.println(blogById1);
sqlSession.close();
}
二级缓存也叫全局缓存,一级缓存作用域太低了,所以诞生了二级缓存
基于namespace级别的缓存,一个mapper.xml文件对应一个二级缓存
一个会话查询一条数据,这个数据就会被放在当前会话的一级缓存中;
如果当前会话关闭了,这个会话对应的一级缓存就没了;
但是我们想要的是,会话关闭了,一级缓存中的数据被保存到二级缓存中,新的会话查询信息,就可以从二级缓存中获取内容;
不同的mapper查出的数据会放在自己对应的缓存(map)中;
<setting name="cacheEnabled" value="true"/>
<!--配置二级缓存-->
<cache eviction="FIFO"
flushInterval="60000"
size="512"
readOnly="true"
/>
<!--这个更高级的配置创建了一个 FIFO 缓存(文件的输入输出),每隔 60 秒刷新,最多可以存储结果对象或列表的 512 个引用,而且返回的对象被认为是只读的,因此对它们进行修改可能会在不同线程中的调用者产生冲突-->
@Test
public void testGetBlogById() {
SqlSession sqlSession = MybatisUtil.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
Blog blogById = mapper.getBlogById(1);
System.out.println(blogById);
sqlSession.close();
SqlSession sqlSession2 = MybatisUtil.getSqlSession();
BlogMapper mapper1 = sqlSession2.getMapper(BlogMapper.class);
Blog blogById1 = mapper1.getBlogById(1);
System.out.println(blogById1);
sqlSession2.close();
}
代码如下(示例):
@Test
public void test3() {
SqlSession sqlSession = MybatisUtil.getSqlSession();
BlogMapper blogMapper = sqlSession.getMapper(BlogMapper.class);
Blog blogById = blogMapper.getBlogById(1);
System.out.println(blogById);
System.out.println("-----------");
int i = blogMapper.deleteBlog(3);
System.out.println(i);
SqlSession sqlSession1 = MybatisUtil.getSqlSession();
BlogMapper blogMapper1 = sqlSession1.getMapper(BlogMapper.class);
Blog blogById1 = blogMapper1.getBlogById(1);
System.out.println(blogById1);
System.out.println(blogById == blogById1);
sqlSession.close();
}
可能出现实体类未序列化问题,需要实体类继承序列化接口。
- 只要开启了二级缓存,在同一个Mapper中的查询,可以在二级缓存中拿到数据