> 文章列表 > mybatis缓存的详细理解和使用

mybatis缓存的详细理解和使用

mybatis缓存的详细理解和使用

mybatis缓存的简单理解和使用

mybatis缓存数据的介绍

缓存是存在于内存中的临时数据,使用缓存的目的是减少和数据库的数据进行交互的次数,提高执行效率。像很多持久化框架一样,Mybatis也提供了缓存策略,通过缓存策略来减少数据库的查询次数,从而提高性能,Mybatis中缓存分为一级缓存和二级缓存

在这里插入图片描述

创建maven模块项目:

在这里插入图片描述

准备配置文件:pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.etime</groupId><artifactId>day12</artifactId><version>1.0-SNAPSHOT</version><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target></properties><dependencies><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.16</version></dependency><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.1</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.11</version><scope>runtime</scope></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version></dependency></dependencies>
</project>

config.xml

编写核心配置文件,将setting 配置日志logImpl…到properties和typeAliases之间

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><properties resource="jdbc.properties"></properties><settings><setting name="logImpl" value="STDOUT_LOGGING"/></settings><typeAliases><package name="com.etime.pojo"/></typeAliases><!--    配置 mybatis的环境--><environments default="development"><!--        配置环境--><environment id="development"><!--            配置事物类型--><transactionManager type="JDBC"></transactionManager><!--            配置连接数据库的信息:用的是数据源[连接池]--><dataSource type="POOLED"><property name="driver" value="${jdbc.driver}"/><!--                jdbc:mysql://localhost:3306/db_school?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC--><!--                和javaWeb servlet三层架构中的区别这里是只需要设置时区就可以了jdbc:mysql://localhost:3306/db_school?serverTimezone=UTC--><property name="url" value="${jdbc.url}"/><property name="username" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/></dataSource></environment></environments><!--    注册StudentDao接口映射文件位置--><mappers><package name="com.etime.mapper"/></mappers>
</configuration>

jdbc.properties

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/db_418?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC
jdbc.username=root
jdbc.password=h123456

SqlSessionUtil.java

package com.etime.util;import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;import java.io.IOException;
import java.io.InputStream;public class SqlSessionUtil {private static  SqlSession sqlSession =null;static {//加载配置文件InputStream inputStream = null;try {inputStream = Resources.getResourceAsStream("config.xml");} catch (IOException e) {e.printStackTrace();}//用于读取配置文件内容,生成SqlSessionFactorySqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);//获取SqlSession对象//参数为true,则底层调用setAutoCommit方法时,sqlSession = sqlSessionFactory.openSession(true);}public SqlSession getSqlSession(){return sqlSession;}
}

一级缓存

mybatis一级缓存一种是session级别的,针对同一个会话SqlSession中,执行多次条件完全相同一个sql,那么会共享这一缓存。

其特点是它是自带的,不能卸载,通过SqlSession级别的缓存,使用无需配置。

Student.java

package com.etime.pojo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;@AllArgsConstructor
@NoArgsConstructor
@Data
public class Student {private int sid;private String sname;private int cid;
}

StudentMapper.java

package com.etime.mapper;import com.etime.pojo.Student;import java.util.List;public interface StudentMapper {List<Student> getAllStudent();
}

编写学生持久层映射文件StudentMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.etime.mapper.StudentMapper"><!--    resultType="stu"--><select id="getAllStudent" resultType="Student">select * from student</select>
</mapper>

编写测试方法:

package com.etime.demo;import com.etime.mapper.StudentMapper;
import com.etime.pojo.Student;
import com.etime.util.SqlSessionUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;import java.util.List;public class MybatisTest {SqlSessionUtil sqlSessionUtil =new SqlSessionUtil();@Testpublic void t01(){SqlSession sqlSession = sqlSessionUtil.getSqlSession();StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);List<Student> list = studentMapper.getAllStudent();list.forEach(System.out::println);System.out.println("---------------------------------");List<Student> list1 = studentMapper.getAllStudent();list1.forEach(System.out::println);}
}

运行结果:

在这里插入图片描述

一级缓存的分析总结

从以上的测试结果来看我们是通过两次查询的方式,只有第一次是在一级缓存中没有数据,是因为session是新创建的,所以第一次的数据是实实在在从数据库中查询出来的。然后会接着让数据放入到一级缓存中去的,此时要注意的是,一级缓存是一个Map集合,map的key是你的查询条件字符串,值就是查询出来的对象。到第二次查询的时候,就是直接到一级缓存中将数据取出的。这样大大减少了和数据的一次交互,提高了执行效率。

二级缓存

二级缓存:默认条件下是不开启的使用时需要进行配置

二级缓存是mapper映射级别的缓存,多个SqlSession去操作同一个Mapper映射的sql语句,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession的。

配置:通过设置cacheEnable设置二级缓存开启

<!--        开启二级缓存--><setting name="cacheEnabled"  value="true"/>

配置statement上面的useCache属性,当useCache设置为true时需要使用二级缓存。如果不适用二级缓存可以设置false

注意的是:针对每次查询都需要最新的数据sql,要设置成useCache=false,禁用二级缓存

<mapper namespace="com.etime.mapper.StudentMapper"><!-- 需要配置cache --><cache></cache><!--    resultType="stu"--><select id="getAllStudent" resultType="Student" useCache="true">select * from student</select>
</mapper>

实体类需要序列化

package com.etime.pojo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.Serializable;@AllArgsConstructor
@NoArgsConstructor
@Data
public class Student implements Serializable {private int sid;private String sname;private int cid;
}

测试:需要清理缓存,使用commit提交了数据只是把一级缓存清理,可以在二级缓存 中拿到数据,如果使用clearCache时是直接把一级和二级缓存都清理了,所以在从二级缓存中查找数据时就没办法查找到数据

 @Testpublic void t02(){SqlSession sqlSession = sqlSessionUtil.getSqlSession();StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);List<Student> list = studentMapper.getAllStudent();list.forEach(System.out::println);//清理缓存//使用commit提交了数据只是把一级缓存清理,可以在二级缓存中拿取到数据sqlSession.commit();
//        使用clearCache是直接把一级和二级缓存都清理了,所以二级缓存就找不到数据//sqlSession.clearCache();System.out.println("---------------------------------");List<Student> list1 = studentMapper.getAllStudent();list1.forEach(System.out::println);sqlSession.close();}

运行结果:

在这里插入图片描述