2.第一个mybatis程序
思路:搭建环境–>导入mybatis–>编写代码–>测试!
2.1、搭建环境
搭建数据库
CREATE DATABASE mybatis;
USE mybatis;
CREATE TABLE `user`(
`id` INT(10) not NULL PRIMARY KEY,
`name` VARCHAR(30) DEFAULT NULL,
`pwd` VARCHAR(30) DEFAULT NULL
)ENGINE = INNODB,DEFAULT CHARSET=utf8;
INSERT INTO `user` VALUES(1,'lwj','dasd'),
(2,'231','321');
新建项目
- 新建一个普通maven项目
- 删除src目录
- 导入maven依赖
<!--导入依赖-->
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.9</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
</dependencies>
2.2、创建一个模块
- 编写mybatis的核心配置文件
<?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>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?userSSL=true&userUnicode=true"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
</configuration>
- 编写mybatis的工具类
private static SqlSessionFactory sqlSessionFactory;
static {
try {
//获取sqlSessionFactory对象
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession();
}
2.3、编写代码
- 实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
int user;
String name;
String pwd;
}
- Dao接口
public interface UserDao {
List<User> getuserlist();
}
- 接口实现类由原来的UserDaoImpl转变为一个Mapper配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.lwj.dao.UserDao">
<select id="getuserlist" resultType="com.lwj.pojo.User">
select * from user
</select>
</mapper>
2.4 测试
注意点:
org.apache.ibatis.binding.BindingException: Type interface com.lwj.dao.UserDao is not known to the MapperRegistry.
MapperRegistry
- junit测试
3.CRUD
1、namespace
namespace中的包名要和Dao/mapper接口的包名一致!
2、select
选择,查询语句
- id:就是对应的namespace中的方法名
- resultType:Sql语句执行的返回值!
- paramaterType:参数类型!
1.编写接口
//根据id查询用户
User getUser(int id);
2.编写对应的mapper中的SQL语句
<select id="getUser" parameterType="int" resultType="com.lwj.pojo.User">
select * from user where id = #{id};
</select>
3.测试
@Test
public void getUser(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = mapper.getUser(1);
System.out.println(user);
sqlSession.close();
}
3、insert
<insert id="insertUser" parameterType="com.lwj.pojo.User">
insert into user(id, name, pwd) values (#{id} ,#{name}, #{pwd})
</insert>
4、update
<update id="changeUser" parameterType="com.lwj.pojo.User" >
update user set name = #{name}, pwd = #{pwd} where id = #{id}
</update>
5、delete
<delete id="deleteUser" parameterType="int">
delete from user where id = #{id}
</delete>
注意点:
- 增删改需要提交事务!
6、Map
实体类,或者数据库中的表,字段或者参数过多,我们应当考虑使用map
int addUer(Map<String,Object> map);
<insert id="addUser" parameterType="map" >
insert into user(id, name, pwd) values (#{userid} ,#{username}, #{userpwd})
</insert>
public void addUser(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
Map<String, Object> map = new HashMap<>();
map.put("userid",123);
map.put("username","ddd");
map.put("userpwd","123143");
int i = mapper.addUer(map);
sqlSession.close();
}
map传递参数,直接在sql中取出key即可 parameterType=”map”
对象传递参数,直接在sql中取对象的属性即可 parameterType=”object”
只有一个基本类型参数的情况下,可以直接在sql中取到
多个参数用map,或者注解、
8、模糊查询
1.java代码执行的时候,传递通配符%%
List<User> l = mapper.getUserlike("%你%");
2.在sql拼接中使用通配符!
select * from user where name like "%"{name}"%"
select * from user where name like concat('%', #{name},'%' )
4、配置解析
1、核心配置文件
- mybatis-comfig.xml
- Mybatis的配置文件包含了会深深影响Mybatis行为的设置和属性信息
2、环境变量
mybatis可以适应多种环境
不过要记住:尽管可以配置多个环境,但每个sqlsessionFactory实例只能选择一种环境。
学会使用配置多套运行环境!
Mybatis默认的事务管理器就是jdbc,连接池:POOLED
3、属性(properties)
我们可以通过properties属性来实现引用配置文件
这些属性都是可外部配置且可动态替换的,既可以在典型的java属性文件中配置,亦可通过properties元素的子元素来传递。【db.properties】
编写一个配置文件

db.properties
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?userSSL=true&userUnicode=true&characterEncoding=UTF-8
username=root
password=123456
在核心配置文件中引入
<!-- 引入外部配置文件-->
<properties resource="db.properties"/>
- 可以直接引入外部文件
- 可以在其中增加一些属性配置
- 如果两个文件有同一个字段,优先使用外部配置文件的!
4、类型别名(typeAliases)
- 类型别名是为java类型设置一个短的的名字
- 存在的意义仅在与用来减少类完全限定名的冗余
<typeAliases>
<typeAlias alias="User" type="com.lwj.pojo.User" />
</typeAliases>
也可以指定一个包名,mybatis会在包名下面搜索需要的javabean,比如:
扫描实体类的包,它的默认别名就为这个类的类名,首字母小写!
<typeAliases>
<package name="com.lwj.pojo"/>
</typeAliases>
在实体类比较少的时候,使用第一种方式。可以自定义别名
如果实体类十分多,建议使用第二种。
如果需要改别名,在实体类上增加注解
@Alias("user")
public class User {}
5、设置
这是mybatis中极为重要的调整设置,它们会改变mybatis的运行时行为
6、其他配置
- typeHandlers(类对象处理器)
- objectFactory(对象工厂)
- plaugins插件
- …
7、映射器(mappers)
mapperRegistry:注册绑定我们的Mapper文件
1.推荐
<mappers>
<mapper resource="com/lwj/dao/UserMapper.xml"/>
</mappers>
2.使用class文件绑定注册
<mappers>
<mapper class="com.lwj.dao.UserDao"/>
</mappers>
注意点:
- 接口和mapper配置文件必须同名
- 接口和mapper配置文件必须在同一包下
3.使用扫描包进行注入绑定
<mappers>
<package name="com.lwj.dao"/>
</mappers>
注意点:
- 接口和mapper配置文件必须同名
- 接口和mapper配置文件必须在同一包下
8、生命周期
生命周期,和作用域,是至关重要的,因为错误的使用会导致非常严重的 并发问题。
SQLSessionFactoryBuilder:
- 一旦创建了sqlsessionFactory,就不再需要了
- 局部变量
SqlSessionFactory:
- 就是可以为:数据库连接池
- SqlSessionFactory一旦被创建
- 因此sqlsessionfactory的最佳作用域时应用作用域
- 最简单的就是使用单例模式或者静态单例模式
SqlSeeion
- 连接到连接池的一个请求
- sqlsession的实例不是线程安全的,因此是不能被共享的,所以它的最佳作用域是请求或方法作用域
- 用完关闭,否则资源被占用
sqlsession可以获得多个mapper
mapper代表具体的业务
5、解决属性名和字段名不一致的问题
ResultMapper
数据库中二点字段

新建一个项目,拷贝之前,测试实体类字段不一致的情况
public class User {
int user;
String name;
String password;
}
测试出现问题
password = null
解决方法:
- 起别名
<select id="getuserlist" resultType="com.lwj.pojo.User">
select id,name,pwd as password from user;
</select>
2、resultMap
结果集映射
id name pwd
id name password
<!-- 结果集映射-->
<resultMap id="userMap" type="User">
<!-- column数据库中的字段,property实体类中的属性-->
<result column="id" property="user"/>
<result column="name" property="name"/>
<result column="pwd" property="password"/>
</resultMap>
<!-- 只要设置不一致就行-->
- resultMap元素是Mybatis中最重要最强大点元素
- ResultMap的设计思想就是,对于简单的语句根本不需要配置显式的结果映射,而面对复杂一点的语句只需要描述它们关系就行了。
- ResultMap最优秀的地方在与,虽然你已经对它相当的了解了,但是根本就不需要显式地用到他们。
6、日志
6.1、日志工厂
如果一个数据库操作,出现异常,我们需要排错,日志
sout、debug
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>

在Mybatis中具体只用哪一个日志实现,在设置中设定!
STDOUT_LOGGING标准日志输出
6.2、Log4j
先导入log4j的包
<dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency>log4j.properties
#将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码
log4j.rootLogger=DEBUG,console,file
#控制台输出的相关设置
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%c]-%m%n
#文件输出的相关设置
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./log/logFile.log
log4j.appender.file.MaxFileSize=10mb
log4j.appender.file.Threshold=DEBUG
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n
#日志输出级别
log4j.logger.org.mybatis=DEBUG
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
配置log4j为日志实现
<settings> <setting name="logImpl" value="LOG4J"/> </settings>log4j的使用

简单实用
- 在要使用Log4j的类中,导入包import org.apache.log4j.Logger;
- 日志对象,参数为当前类的class
- 日志级别
log.info("进入了info方法");
log.debug("进入了debug方法");
log.error("进入了error方法");
7、分页
- 减少数据的处理量
使用limit分页
语法:SELECT * from `user` LIMIT 0[startindex],2[pageSize]
SELECT * from `user` LIMIT 3;#[0,n]
使用mybatis实现分页,核心sql
接口
//分页 List<User> userListLimit = mapper.getUserListLimit(map);mapper.xml
<!-- 分页--> <select id="getUserListLimit" resultType="com.lwj.pojo.User" parameterType="map"> select id,name,pwd from user limit ${startIndex}, ${pageSize}; </select>测试
@Test public void getUserListLimit(){ Map<String, Integer> map = new HashMap<>(); map.put("startIndex",1); map.put("pageSize",2); SqlSession sqlSession = MybatisUtils.getSqlSession(); UserDao mapper = sqlSession.getMapper(UserDao.class); List<User> userListLimit = mapper.getUserListLimit(map); for (User user: userListLimit) { log.info(user); } sqlSession.close(); }
8、使用注解开发
8.1、使用注解开发
1.注解在接口上实现
@Select("select * from user")
List<User> getUserList();
2.需要在核心配置文件中绑定接口
<!--绑定接口-->
<mappers>
<mapper class="com.lwj.dao.UserDao"/>
</mappers>
3. 测试
本质:反射机制实现
底层:动态代理!

mybatis详细的执行流程
8.2、CRUD
我们可以在工具类创建的时候事项自动提交事务!
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession(true);
}
编写接口,增加注解
User getUserById();
List<User> getUserListLimit(Map<String, Integer> map);
@Select("select * from user")
List<User> getUserList();
@Select("select * from user where id = #{id}")
User getUserById(@Param("id") int id);
@Insert("insert into user(id, name, pwd) values( #{id}, #{name}, #{pwd})")
int addUser(User user);
@Update("update user set name = #{name} , pwd = #{pwd} where id = #{id}")
int updateUser(User user);
@Delete("delete from user where id = #{uid}")
int deleteUser(@Param("uid") int id);
测试类
注意:我们必须要将接口注册绑定到核心配置文件中
@Test
public void getUserList(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
//底层主要应用反射
UserDao mapper = sqlSession.getMapper(UserDao.class);
/* List<User> userList = mapper.getUserList();
for (User user:userList){
log.info(""+user);
}*/
User userByID = mapper.getUserById(1);
log.info(userByID.toString());
/*User user = new User(3,"lwj","123456");
int i = mapper.updateUser(user);*/
int i = mapper.deleteUser(1);
// int i = mapper.addUser(user);
log.info(i+"");
sqlSession.close();
}
关于@param()注解
- 基本类型参数或者String类型,需要加上
- 引用类型不需要加
- 如果只有一个基本类型,可以忽略,建议加上
- 在sql中引用的就是我们这里的@param(“uid”)中设定的属性名!
#{} ${}区别
https://blog.csdn.net/weixin_41231928/article/details/105120292
9、lomobk
java library
plugs
build tools
annotation
使用步骤:
新版idea已经将lombok插件内置其中
使用maven导入Lombok jar包
@Date
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@ToString
10、多对一处理
环境搭建测试
导入Lombok
新建实体类Teacher, student
建立mapper接口
建立Mapper.xml文件
在核心配置文件中绑定我们的Mapper接口或文件
测试查询是否能够成功
按照查询嵌套处理
<!--
思路:
1.查询所有的学生信息
2.根据查询出来的学生的tid,寻找对应的老师! 子查询
-->
<resultMap id="StudentTeacher" type="com.lwj.pojo.Student">
<result property="id" column="id"/>
<result property="name" column="name"/>
<!--复杂的属性,我们需要单独处理 对象:association 集合:collection-->
<association property="user" column="uid" javaType="User" select="getTeacher"/>
</resultMap>
<select id="getStudent" resultMap="StudentTeacher">
select * from student
</select>
<select id="getTeacher" resultType="com.lwj.pojo.User">
select * from user where id = #{id}
</select>
按照结果嵌套处理
<!-- =================================================================== -->
<!-- 按照结果嵌套处理 -->
<!--
1.查询所有的学生信息
2.根据查询出来的学生的tid,寻找对应的老师!
-->
<select id="getStudent2" resultMap="StudentTeacher2">
select s.id sid,s.name sname,u.name tname,u.pwd,u.id from student s , user u where s.uid = u.id;
</select>
<resultMap id="StudentTeacher2" type="com.lwj.pojo.Student">
<result property="id" column="sid"/>
<result property="name" column="sname"/>
<association property="user" javaType="User">
<result property="name" column="tname"/>
<result property="pwd" column="pwd"/>
<result property="id" column="id"/>
</association>
</resultMap>
mysql多对一查询方式:
- 子查询
- 联表查询
11、一对多处理
比如:一个老师拥有多个学生!
对于老师而言,就是一对多的关系!
1、环境搭建,和刚才的一样
实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
private int id;
private String name;
private int tid;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
int id;
String name;
String pwd;
//一个老师拥有多个学生
private List<Student> students;
}
按照结果嵌套处理
<!-- 按结果嵌套查询-->
<select id="getUserById" resultMap="TeacherStudent">
select s.id sid , s.name sname ,t.name tname, t.id tid
from student s,user t
where s.id = t.id and t.id = #{id}
</select>
<resultMap id="TeacherStudent" type="Teacher">
<result property="id" column="tid"/>
<result property="name" column="tname"/>
<!-- 复杂的属性,我们需要单独处理 对象assoction 集合 collection
javatype="" 指定属性的类型!
集合中的泛型信息,我们使用oftype获取
-->
<collection property="students" ofType="Student">
<result property="id" column="sid"/>
<result property="name" column="sname"/>
<result property="tid" column="tid"/>
</collection>
</resultMap>
按照查询嵌套处理
<select id="getTeacher2" resultMap="TeacherStudent2">
select * from user where id = #{id}
</select>
<resultMap id="TeacherStudent2" type="Teacher">
<result property="id" column="id"/>
<result property="name" column="name"/>
<result property="pwd" column="pwd"/>
<collection property="students" javaType="ArrayList" ofType="Student" select="getStudentByTeacherId" column="id"/>
</resultMap>
<select id="getStudentByTeacherId" resultType="Student">
select *
from student
where id = #{id};
</select>
小结
- 关联-assoction
- 集合-collection
- javatype & of type
1. javatype 用来指定实体类属性的类型 2. oftype 用来指定映射到list或者集合中的pojo类型,泛型中的约束类型
注意点:
- 保证sql的可读性,尽量通俗易懂
- 注意一对多和多对一中,属性名和字段的问题
- 如果要排查问题,使用日志。
12、动态sql
动态sql,就是根据不同的条件生成不同的sql语句
使用动态sql特性
如果你之前用过 JSTL 或任何基于类 XML 语言的文本处理器,你对动态 SQL 元素可能会感觉似曾相识。在 MyBatis 之前的版本中,需要花时间了解大量的元素。借助功能强大的基于 OGNL 的表达式,MyBatis 3 替换了之前的大部分元素,大大精简了元素种类,现在要学习的元素种类比原来的一半还要少。
- if
- choose (when, otherwise)
- trim (where, set)
- foreach
搭建环境
CREATE TABLE `blog`(
`id` VARCHAR(50) NOT NULL COMMENT '博客id',
`title` VARCHAR(100) NOT NULL COMMENT '博客标题',
`author` VARCHAR(30) NOT NULL COMMENT '博客作者',
`create_time` DATETIME NOT NULL COMMENT '创建时间',
`views` INT(30) NOT NULL COMMENT '浏览量'
)ENGINE=INNODB DEFAULT CHARSET=utf8;
创建一个基础工程
- 导包
- 编写配置文件
- 编写实体类
@Data
public class Blog {
private int id;
private String title;
private String author;
private Date createTime;
private int views;
}
- 编写实体类对应Mapper接口和mapper.xml文件
IF
<select id="queryBlogIF" parameterType="Map" resultType="blog">
select *
from blog
<where>
<if test="title != null">
and title = #{title}
</if>
<if test="author != null">
and author = #{author}
</if>
</where>
</select>
choose (when, otherwise)
<select id="queryBlogChoose" parameterType="Map" resultType="blog">
select *
from blog
<where>
<choose>
<when test="title != null">
title = #{title}
</when>
<when test="author != null">
and author = #{author}
</when>
<otherwise>
and views = #{views}
</otherwise>
</choose>
</where>
</select>
trim (where, set)
<select id="queryBlogIF" parameterType="Map" resultType="blog">
select *
from blog
<where>
<if test="title != null">
title = #{title}
</if>
<if test="author != null">
and author = #{author}
</if>
</where>
</select>
<update id="updateBlog" parameterType="Map">
update blog
<set>
<if test="title != null">
title = #{title},
</if>
<if test="author != null">
author = #{author}
</if>
</set>
where id = #{id}
</update>
所谓的动态sql,本质还是sql语句,只是可以在sql层面,去执行一个逻辑代码
if
where,set,choose,when
sql片段
有时,将一些功能的部分抽取出来,方便复用!
- 使用sql标签抽取公共部分
<sql id="if-title-author">
<if test="title != null">
title = #{title},
</if>
<if test="author != null">
author = #{author}
</if>
</sql>
- 在需要的使用的地方使用include标签引用即可
<update id="updateBlog" parameterType="Map">
update blog
<set>
<include refid="if-title-author"></include>
</set>
where id = #{id}
</update>
注意事项:
- 最好基于单表来定义sql标签
- 不要存在where,set等标签
Foreach
select * from user where 1=1 and
<foreach item="id" index="index" collection="ids"
open="(" separtor="or" close=")">
#{id}
</foreach>
(id=1 or id=2 or id=3)
<!-- 传递map,map中可以存在一个集合 map中的key的名ids是个列表-->
<select id="queryBlogForeach" parameterType="Map" resultType="blog">
select *
from blog
<where>
<foreach collection="ids" item="id" open="and (" close=")" separator="or">
id = #{id}
</foreach>
</where>
</select>
动态sql就是在拼接sql语句,只要保证sql的正确性,按照sql的格式,去排列组合就可以了
建议在mysql中写出sql语句,在修改为对应的动态sql语句
13、缓存
13.1、简介
查询:连接数据库,耗资源!
一次查询的结果,给他暂存在一个可以直接取到的地方!-->内存:缓存
再次查匈奴相同的数据时候,直接走缓存,就不用走数据库了
什么是缓存?
- 存在内存中的临时数据。
- 将用户经常查询的数据放在缓存中,用户去查询数据就不用从磁盘上查询,从缓存中查询,从而提高查询效率,解决了高并发系统的性能问题。
为什么使用缓存?
- 减少和数据库的交互次数,减少系统开销,提高系统效率。
什么样的数据能使用缓存?
- 经常查询并且不经常改变的数据。
13.2、mybatis缓存
- mybatis包含一个非常强大的查询缓存特性,它可以非常方便的定制和配置缓存。缓存可以极大的提升查询效率。
- mybatis系统中默认定义了两级缓存:一级缓存和二级缓存
- 默认情况下,只有一级缓存开启。(sqlsession级别的缓存,也称为本地缓存)
- 二级缓存需要手动开启和配置,他是基于namespace级别的缓存。
- 为了提高扩展性,mybatis定义了缓存接口cache。我们可以通过实现cache接口来自定义二级缓存。
13.3、一级缓存
- 一级缓存也叫本地缓存:SQL session
- 与数据库同一次会话期间查询到的数据会放在本地数据缓存中
- 以后如果需要获取相同的数据,直接从缓存中拿,没必要再去查询数据库
测试步骤:
- 开启日志
- 测试在一个sesion中查询两次相同的记录
- 查看日志输出
缓存失效情况
查询不同的东西
增删改操作,可能会改变原来的数据,所以必定会刷新缓存!
查询不同的mapper.xml
手动清理缓存

小结:一级缓存默认是开启的,只在一次sqlsession中有效,也就是拿到连接到关闭连接这个区间段!
一级缓存相当于一个map。
13.4、二级缓存
- 二级缓存也叫全局缓存,一级缓存作用域太低了,所以诞生了二级缓存
- 基于namespace级别的缓存,一个名称控件,对应一个二级缓存;
- 工作机制
- 一个会话查询一条数据,这个数据就会被放在当前会话的一级缓存中;
- 如果当前会话关闭了,这个会话对应的一级缓存就没了;但是我们想要的是,会话关闭了,一级缓存中的数据被保存到二级缓存中
- 新的会话查询信息,就可以从二级缓存中获取内容
- 不同的mapper查出的数据会放在自己对应的缓存(map)中
步骤:
- 开启全局缓存
<!-- 显示的开启全局缓存 ,默认开启-->
<setting name="cacheEnabled" value="true"/>
- 在要使用二级缓存的mapper中开启
<!-- 在当前mapper.xml中使用二级缓存-->
<cache/>
<!-- 也可以自定义参数-->
<cache eviction="FIFO"
flushInterval="60000"
size="512"
readOnly="true"
/>
- 测试
- 问题:我们需要将实体类进行序列化!否则会报错
- 所有的数据都会放在一级缓存中!
- 只有当会话提交,或者关闭的时候,才会提交到二级缓存中!
13.5、缓存原理

13.6、自定义缓存-ehcache
Ehcache是一种广泛使用的开源Java分布式缓存。主要面向通用缓存,Java EE和轻量级容器。
要在程序中使用ehcache,先要导包!
在mapper中指定使用我们的ehcache缓存实现!
<!-- 在当前mapper.xml中使用二级缓存-->
<cache type="org.mybatis.caches.ehcache.EhBlockingCache"
/>
redis数据库来做缓存! k-v键值对