😀😀😀创作不易,各位看官点赞收藏.
文章目录
MyBatis 学习笔记
简介:MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。简单来说,mybatis就是用来操作数据库的,可以使程序猿更加容易书写 dao 层。
1、Mybatis Demo 程序
搭建环境:导入依赖、创建数据库表
user(id,name,address)
。
<!-- junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
</dependency>
<!-- mybatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<!-- 数据库连接-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
</dependency>
<!-- log4j-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
编写配置文件:mybatis-config.xml,XML 配置文件中包含了对 MyBatis 系统的核心设置,包括获取数据库连接实例的数据源(DataSource)以及决定事务作用域和控制方式的事务管理器(TransactionManager)。
<?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">
<!--mybatis的主配置文件-->
<configuration>
<!-- 数据库配置环境-->
<!-- default和下面的id名称要一样,默认使用,可以定义多个环境-->
<environments default="mysql">
<!-- 配置mysql的环境-->
<environment id="mysql">
<!-- 配置事务类型为jdbc-->
<transactionManager type="JDBC"/>
<!-- 配置数据池连接源-->
<!-- type有三种类型
1、POOLED是使用数据库连接池的类型
2、UNPOOLED是不适用数据库连接池的类型
3、JNDI是JNDI类型的数据源 JndiDataSource
-->
<dataSource type="POOLED">
<!-- 配置数据库的4个基本信息-->
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///mybatis?characterEncoding=utf-8&serverTimezone=UTC"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<!-- 引入映射文件-->
<mappers>
<mapper resource="mapper/UserMapper.xml"/>
</mappers>
</configuration>
编写 Mapper 接口:
public interface UserMapper {
// 查询所有的用户
List<User> findAllUser();
}
编写 mapper.xml:
<?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">
<!--namespace会绑定一个mapper接口,可以理解为实现这个接口,必须写全限定类名-->
<mapper namespace="com.jx.app.mybatis.mapper.UserMapper">
<!-- id是接口中的方法名称,resultType是实体的全限定类名,标签体中写sql语句-->
<select id="findAllUser" resultType="com.jx.app.mybatis.entity.User">
select * from user
</select>
</mapper>
编写 Mybatis 工具类:
public class MybatisUtils {
// 成员变量
private static SqlSessionFactory sqlSessionFactory;
// 静态代码初始化
static {
try {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
// 获取sqlSession
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession();
}
}
测试查询结果:
@Test
public void test(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> users = mapper.findAllUser();
System.out.println(users);
}
2、Mybatis 核心配置文件
environments:配置数据库连接配置环境。
<!-- default和下面的id名称要一样,默认使用,可以定义多个环境-->
<environments default="mysql">
<!-- 配置mysql的环境,id是唯一标识不能重复-->
<environment id="mysql">
<!-- 配置事务管理方式:JDBC(原生事务)、MANAGED()-->
<transactionManager type="JDBC"/>
<!-- 配置数据池连接源-->
<!-- type有三种类型
1、POOLED是使用数据库连接池的类型
2、UNPOOLED是不适用数据库连接池的类型
3、JNDI使用上下文的数据源
-->
<dataSource type="POOLED">
<!-- 配置数据库的4个基本信息-->
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql:///mybatis?characterEncoding=utf-8&serverTimezone=UTC"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
propertes:可以引入 properties 文件,然后通过某种方式去访问文件中的值。
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql:///mybatis?characterEncoding=utf-8&serverTimezone=UTC
username=root
password=123456
<!-- 引入文件,然后可以在下面通过 ${key值} 获取对应的value-->
<properties resource="jdbc.properties"/>
settings:Mybatis 的全局配置,还有很多配置,可以去官网上查看。
<settings>
<!-- 字段名与属性名驼峰命名映射:user_name == userName-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
<!-- 指定 mybatis 中的日志输出-->
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
typeAliases:取别名标签,给实体类取一个别名,在映射结果时就可以使用别名就不再使用全限定类名。
<typeAliases>
<!-- 在编写 mapper 映射文件时就可以使用 User 来代替这个全限定类名,不设置 alias 别名就是类名-->
<typeAlias type="com.jx.app.mybatis.entity.User" alias="User"/>
<!-- 把指定包下的所有类都起别名,别名都是类名-->
<package name="com.jx.app.mybatis.entity"/>
</typeAliases>
mappers:引入 mapper 映射文件。
<!-- 引入映射文件-->
<mappers>
<!-- 需要引入 mapper 文件存放在 resources 目录下-->
<mapper resource="mapper/UserMapper.xml"/>
<!-- 通过包名进行引入:1、mapper 文件名需要与接口一样,2、mapper 存放的目录结构也必须和接口保持一致-->
<package name="com.jx.app.mybatis.mapper"/>
</mappers>
3、Mybatis Mapper 传参映射
在 mapper 映射文件获取接口的参数有两种方式,${}
和 #{}
。
${}
: 本质是字符串拼接,将参数与 SQL 语句进行简单拼接,这种方式可能存在 SQL 注入问题,使用这种方式需要注意字符串的单引号拼接。#{}
:本质是占位符方式来拼接 SQL,自动给参数加上单引号,这种方式防止 SQL 注入问题。
单个字面量参数:
// 参数 name 是单个字面量
User getUserByName(String name);
<select id="getUserByName" resultType="com.jx.app.mybatis.entity.User">
SELECT *
FROM user u
WHERE u.user_name = #{name}
<!-- name参数需要和接口参数名保持一致-->
</select>
多个字面量参数:
// 存在多个参数
User getUser(String id, String name);
<!-- 如果存在多个参数,那么 mybatis 会把参数存储在一个 map 中,key:[arg0,arg1...,param1,param2...]
可以通过对应的键获取参数值,但是不能通过参数名去获取,这两种 key 可以混用,顺序就是指定的下标
-->
<select id="getUser" resultType="com.jx.app.mybatis.entity.User">
SELECT *
FROM user u
<!-- WHERE u.id = #{arg0} AND u.user_name = #{arg1}-->
WHERE u.id = #{param1} AND u.user_name = #{param2}
</select>
map 传参:
// 参数是一个map
User getUserByMap(Map<String,String> map);
<!-- 参数是一个 map,可以直接根据 key 获取对应的值-->
<select id="getUserByMap" resultType="com.jx.app.mybatis.entity.User">
SELECT *
FROM user u
WHERE u.id = #{id} AND u.user_name = #{username}
</select>
实体类传参:
// 参数是一个是实体类
int insert(User user);
<!-- 参数是实体类,可以通过类的属性名获取对应的属性值-->
<insert id="insert">
INSERT INTO user values(null,#{userName},#{password},#{money})
</insert>
@param
注解:可以命名参数,标识参数后依然后把参数放入 map 中,可以通过命名参数的 key 来获取参数值。
// @Param 将参数进行取别名命名
User getUser(@Param("id") String id, @Param("name") String name);
<!-- 使用 @param 注解后可以直接使用对应的命名 key 获取对应的值-->
<select id="getUser" resultType="com.jx.app.mybatis.entity.User">
SELECT *
FROM user u
WHERE u.id = #{id} AND u.user_name = #{name}
</select>
4、Mybatis 查询结果
查询结果为实体对象:
// 接口返回值为实体对象
User getUserByName(String name);
<!-- resultType:属性需要指定返回值的全限定类名或者是别名-->
<select id="getUserByName" resultType="com.jx.app.mybatis.entity.User">
SELECT *
FROM user u
WHERE u.user_name = #{name}
</select>
注意:返回值是一个实体类对象时,返回结果只能是一条数据或者 null,如果查询出来是多条数据就会报错。
查询结果为集合:
// 接口返回值为集合类型,并指定对应泛型
List<User> getUserByName(@Param("name") String name);
<!-- resultType:需要指定集合中泛型对应类的全限定类名或者别名-->
<select id="getUserByName" resultType="com.jx.app.mybatis.entity.User">
SELECT * FROM user u
</select>
注意:如果查询出来一条或多条结果就会封装到集合中,如果没有结果就会返回空集合但是不会返回 null。
查询结果为 map 集合:
// 接口返回值是map类型
Map<String,Object> getUserToMap();
<!-- 将查询的接口以字段名为key,然后字段值为 value 的 map-->
<select id="getUserToMap" resultType="java.util.Map">
SELECT * FROM user u
</select>
注意:查询结果为 map 只能查询一条数据,查询出多条就会报错,而且如果某个字段是 null,这个字段不会封装到 map 中。
多条结果封装成 map:
/**
* 如果查询多条数据也想封装成 map,@MapKey 可以指定查询出来那个字段可以作为 key,
* 然后这一条数据又会封装成一个 map 作为 value 存储进去
*/
@MapKey("id")
Map<String, Map<String,Object>> getUserToMap();
获取自增主键:在插入数据时,可以获取插入数据后对应的自动递增的 id。
// 插入元素
int insert(User user);
<!--
useGeneratedKeys:设置是否能够获取到自增主键
keyProperty:获取到的主键的值存储到参数实体的哪个属性
-->
<insert id="insert" useGeneratedKeys="true" keyProperty="id">
INSERT INTO user values(null,#{userName},#{password},#{money})
</insert>
resultMap 字段关系映射:查询出来的结果与实体类上的字段名称不一致,我们就需要通过 resultMap 属性去自定义映射关系。
方式一:字段起别名,可以在 SQL 语句中把字段名通过起别名方式与属性名一一对应。
方式二:使用 resultMap 映射,将查询出来字段名与对象属性名进行一个自定义映射。
<!-- 设置返回值类型为 resultMap,并且创建一个映射-->
<select id="getUserList" resultMap="UserListMap">
SELECT * FROM user u
</select>
<!-- 关系映射,id属性:需要和映射返回值相同,type属性:就是映射的实体对象类型-->
<!-- id:数据库主键字段,result:普通字段。
column属性:查询数据库对应字段名,property属性:需要映射的属性名称。
-->
<resultMap id="UserListMap" type="com.jx.app.mybatis.entity.User">
<id column="id" property="id"/>
<result column="user_name" property="userName"/>
<result column="password" property="password"/>
<result column="money" property="money"/>
</resultMap>
注意:如果查询出来字段名与属性名对应不上,不会报错,只是他们对应属性值都是对象默认值。
5、Mybatis 关系映射处理
两个实体:Student 和 Teacher,一个学生有一个老师,一个老师有多个学生。
@Data
public class Student {
private String id;
private String studentName;
private Teacher teacher;
}
@Data
public class Teacher {
private String id;
private String teacherName;
private List<Student> students;
}
5.1、多对一关系映射处理
方式一:使用连接查询查询对学生对应的老师信息,然后使用级联属性映射。
<!-- 使用连接查询获取学生信息以及老师信息-->
<select id="getStudentById" resultMap="StudentMap">
SELECT * FROM student s
LEFT JOIN teacher t ON s.t_id = t.id
WHERE s.id = #{id}
</select>
<!-- 使用级联方式进行属性映射-->
<resultMap id="StudentMap" type="com.jx.app.mybatis.entity.Student">
<id column="id" property="id"/>
<result column="student_name" property="studentName"/>
<result column="t_id" property="teacher.id"/>
<result column="teacher_name" property="teacher.teacherName"/>
</resultMap>
方式二:使用连接查询查询对学生对应的老师信息,然后通过 resultMap 进行关系映射。
<!-- 使用连接查询获取学生信息以及老师信息-->
<select id="getStudentById" resultMap="StudentMap">
SELECT * FROM student s
LEFT JOIN teacher t ON s.t_id = t.id
WHERE s.id = #{id}
</select>
<!-- 使用 association 关系映射-->
<resultMap id="StudentMap" type="com.jx.app.mybatis.entity.Student">
<id column="id" property="id"/>
<result column="student_name" property="studentName"/>
<!-- property:需要映射的属性名,javaType:这个属性的 java 类型是什么-->
<association property="teacher" javaType="com.jx.app.mybatis.entity.Teacher">
<id column="t_id" property="id"/>
<result column="teacher_name" property="teacherName"/>
</association>
</resultMap>
方式三:通过子查询去查询老师信息,然后通过 resultMap 进行关系映射。
<!-- 先获取学生信息-->
<select id="getStudentById" resultMap="StudentMap">
SELECT * from student WHERE id = #{id}
</select>
<resultMap id="StudentMap" type="com.jx.app.mybatis.entity.Student">
<id property="id" column="id"/>
<result property="studentName" column="student_name"/>
<!-- select:子查询的唯一标识(命名空间+id),column:给子查询的查询参数-->
<association property="teacher" select="com.jx.app.mybatis.mapper.UserMapper.getTeacher" column="t_id"/>
</resultMap>
<!-- 子查询-->
<select id="getTeacher" resultType="com.jx.app.mybatis.entity.Teacher">
SELECT * from teacher where id = #{t_id}
</select>
注意:子查询有一个好处就是可以设置关联对象的延迟加载,只有在使用到延迟对象时才会去执行对应的子查询 SQL 语句然后返回结果。
- 需要开启 mybatis 的全局懒加载设置,
<setting name="lazyLoadingEnabled" value="true"/>
。 - association 有一个 fetchType 属性手动控制懒加载,值有 lazy(懒加载)、eager(立即加载),如果不设置这个属性默认是懒加载。
5.2、一对多关系映射处理
方式一:通过连接查询出老师对应的所有学生信息,然后通过 resultMap 进行关系映射。
<!-- 连接查询-->
<select id="getTeacherById" resultMap="TeacherMap">
SELECT * FROM teacher t
LEFT JOIN student s ON t.id = s.t_id
WHERE t.id = #{id}
</select>
<resultMap id="TeacherMap" type="com.jx.app.mybatis.entity.Teacher">
<id property="id" column="id"/>
<result property="teacherName" column="teacher_name"/>
<!-- 查询出来学生信息进行集合映射,ofType:集合泛型中的属性-->
<collection property="students" ofType="com.jx.app.mybatis.entity.Student">
<id property="id" column="s_id"/>
<result property="studentName" column="student_name"/>
</collection>
</resultMap>
方式二:分步查询老师信息和学生信息,然后通过 resultMap 映射关联。
<select id="getTeacherById" resultMap="TeacherMap">
SELECT * FROM teacher t
WHERE t.id = #{id}
</select>
<resultMap id="TeacherMap" type="com.jx.app.mybatis.entity.Teacher">
<id property="id" column="id"/>
<result property="teacherName" column="teacher_name"/>
<!-- 查询出来学生信息进行集合映射,ofType:集合泛型中的属性-->
<collection property="students" ofType="com.jx.app.mybatis.entity.Student"
select="com.jx.app.mybatis.mapper.UserMapper.getStudent"
column="id">
</collection>
</resultMap>
<select id="getStudent" resultType="com.jx.app.mybatis.entity.Student">
select * from student where t_id = #{tid}
</select>
6、Mybatis 动态 SQL
根根据特定的条件动态拼接 SQL 语句的功能,它就是解决在拼接 SQL 时字符串问题。
if 标签:会根据标签的 test 属性对应表达式返回 true 或者 false 决定是否拼接到 SQL 语句中。
// 使用 if 进行多条件查询
List<User> DynamicSQL(User user);
<select id="DynamicSQL" resultType="com.jx.app.mybatis.entity.User">
select * from user
where 1=1
<!-- 如果查询条件有 username 就会在 SQL 中进行拼接-->
<if test="userName != null and userName != ''">
and user_name = #{userName}
</if>
<if test="money != null and money != ''">
and money = #{money}
</if>
</select>
where 标签:动态生成 where 条件语句,根据拼接 SQL 在前面添加或去掉 and、or 关键字,如果没有条件就不会有 where 关键字。
<select id="DynamicSQL" resultType="com.jx.app.mybatis.entity.User">
select * from user
<!-- 会动态生成 where 关键字,并且去除或添加开头的 and、or 关键字-->
<where>
<!-- 如果查询条件有 username 就会在 SQL 中进行拼接-->
<if test="userName != null and userName != ''">
and user_name = #{userName}
</if>
<if test="money != null and money != ''">
or money = #{money}
</if>
</where>
</select>
trim 标签:如果拼接 SQL 字符串有内容可以在内容前后添加内容,如果没有内容也没有任何效果。
<select id="DynamicSQL" resultType="com.jx.app.mybatis.entity.User">
select * from user
<!--
prefix|suffix:在内容的前面|后面添加指定内容
prefixOverrides|suffixOverrides:在内容的前面|后面去掉指定内容
-->
<trim prefix="where" suffix="" prefixOverrides="and|or" suffixOverrides="">
<if test="userName != null and userName != ''">
and user_name = #{userName}
</if>
<if test="money != null and money != ''">
or money = #{money}
</if>
</trim>
</select>
chose…when…otherwise 标签:相当于 if…eles if…else,指定条件选择一个进行执行,其它内容不执行。
<select id="DynamicSQL" resultType="com.jx.app.mybatis.entity.User">
select * from user
<where>
<!-- 只选择一个条件进行执行,如果 when 都不满足则执行 otherwise 中的内容-->
<choose>
<when test="userName != null and userName != ''">
user_name = #{userName}
</when>
<when test="money != null and money != ''">
money = #{money}
</when>
<otherwise>
id = #{id}
</otherwise>
</choose>
</where>
</select>
注意:这个条件选择执行只会满足一个,要么是 when 中的一个要么就是 otherwise。
foreach 标签:如果参数是集合类型,可以通过标签遍历集合中内容,例如进行批量删除、增加等操作。
// 批量删除
int deleteBatch(@Param("ids") List<String> ids);
<delete id="deleteBatch">
delete from user
<where>
id in
<!-- collection:操作的集合参数,item:遍历出来的每个元素,open:指定开始内容,
close:指定结束内容,index:遍历到的下标,separator:指定每个元素之间的分隔符
-->
<foreach collection="ids" item="id" close=")" open="(" separator="," index="i">
#{id}
</foreach>
</where>
</delete>
sql 标签:对常用的 SQL 语句进行一个抽取,如果在其它地方使用直接引用。
<!-- id:唯一标识 sql 标签,在引用时通过 id 引入-->
<sql id="CommonSQL">
id,user_name,password,money
</sql>
<!-- 通过 include 标签进行引入动态的 sql-->
<select id="selectAll" resultType="com.jx.app.mybatis.entity.User">
select <include refid="CommonSQL"/> from user
</select>
7、Mybatis 缓存
一级缓存:这个级别缓存是 SqlSession 级别的缓存,通过同一个 SqlSession 对象去查询数据,那么在第二次查询就会去缓存中获取而不会去查询数据库,这种缓存是默认开启的。
@Test
public void test4(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper userMapper1 = sqlSession.getMapper(UserMapper.class);
List<User> allUser1 = userMapper1.findAllUser();
System.out.println(allUser1);
// 即使是不同 mapper 对象,但是是同一个 sqlSession,那么第二次就会去缓存中取数据
UserMapper userMapper2 = sqlSession.getMapper(UserMapper.class);
List<User> allUser2 = userMapper2.findAllUser();
System.out.println(allUser2);
}
一级缓存失效:
- 使用不同的 SqlSession 进行查询数据。
- 同一个 SqlSession 但是查询条件不同。
- 同一个 SqlSession 的两次查询之间执行了其它的增、删、改等操作。
- 同一个 SqlSession 的两次查询之间手动清空了缓存。
// 手动清空缓存
sqlSession.clearCache();
二级缓存:二级缓存是 SqlSessionFactory 级别的缓存,通过同一个 SqlSessionFactory 创建的 SqlSession 去查询结果会被缓存,那么第二次去执行相同查询就会去缓存中查询,二级缓存需要手动开启。
- 需要在 mybatis 核心配置文件中开启缓存。
<settings>
<!-- 开启全局缓存,默认是开启的-->
<setting name="cacheEnabled" value="true"/>
</settings>
- 在 mapper 映射文件中开启缓存。
<!-- 开启缓存-->
<cache />
@Test
public void test5(){
SqlSession sqlSession1 = MybatisUtils.getSqlSession();
SqlSession sqlSession2 = MybatisUtils.getSqlSession();
UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class);
List<User> users1 = mapper1.selectAll();
System.out.println(users1);
sqlSession1.commit();
// 同一个 SqlSessionFactory 获取的不同 SqlSession 查询结果会被缓存
UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class);
List<User> users2 = mapper2.selectAll();
System.out.println(users2);
}
注意事项:
- 必须是同一个 SqlSessionFactory 的 SqlSession 的二级缓存才会生效。
- 只有每一个将 SqlSession 查询后提交或者关闭,数据才会被缓存。
- 查询的结果对象必须实现序列化,不然使用缓存会报错。
- 两次相同查询之间,执行了增、删、改操作,一级缓存、二级缓存都会失效。
二级缓存相关设置:在 mapper 映射文件中的 cache 标签可以设置以下属性。
<!-- 相关设置:
eviction(缓存回收策略)=LRU(最近最少使用,默认值) | FIFO(先进先出)
flushInterval:缓存刷新时间,单位秒,不设置就是不刷新就只有执行增删改语句才会刷新
size:缓存对象数目,防止内存溢出
readOnly(是否只读)=true(缓存返回是同一个对象,且这个对象不能修改,修改会报错)
false(返回的缓存中的一个拷贝对象,这个对象可以修改,默认值)
-->
<cache eviction="LRU" flushInterval="1000" size="10" readOnly="false"/>
Mybatis 缓存查询顺序:
- 先查询二级缓存,二级缓存的范围比一级缓存大一些。
- 如果二级缓存没有命中就回去查询一级缓存。
- 如果一级缓存也没有命中,就会去查询数据库。
- SqlSession 关闭后,会将一级缓存的数据写入二级缓存。
第三方缓存工具 EHCache:
- 导入依赖:
<!-- ehcache和mybatis整合包-->
<dependency>
<groupId>org.mybatis.caches</groupId>
<artifactId>mybatis-ehcache</artifactId>
<version>1.2.1</version>
</dependency>
- 编写 ehcache 配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<ehcache
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
updateCheck="false">
<!--
diskStore:为缓存路径,ehcache分为内存和磁盘两级,
此属性定义磁盘的缓存位 置。
参数解释如下:
user.home – 用户主目录
user.dir – 用户当前工作目录
java.io.tmpdir – 默认临时文件路径
-->
<diskStore path="E:\ehcache"/>
<defaultCache
eternal="false"
maxElementsInMemory="10000"
overflowToDisk="true"
diskPersistent="false"
timeToIdleSeconds="1800"
timeToLiveSeconds="259200"
memoryStoreEvictionPolicy="LRU"/>
<cache
name="cloud_user"
eternal="false"
maxElementsInMemory="5000"
overflowToDisk="false"
diskPersistent="false"
timeToIdleSeconds="1800"
timeToLiveSeconds="1800"
memoryStoreEvictionPolicy="LRU"/>
<!--name:缓存名称。
maxElementsInMemory:缓存最大数目
maxElementsOnDisk:硬盘最大缓存个数。
eternal:对象是否永久有效,一但设置了,timeout将不起作用。
overflowToDisk:是否保存到磁盘,当系统当机时
timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。 仅当 eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。
timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建 时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存 活时间无穷大。
diskPersistent:是否缓存虚拟机重启期数据 Whether the disk store persists between restarts of the Virtual Machine. The default value is false.diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默 认是30MB。每个Cache都应该有自己的一个缓冲区。
diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。
memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将 会根据指定的策略去清理内存。
默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先 出)或是LFU(较少使用)。
clearOnFlush:内存数量最大时是否清除。 memoryStoreEvictionPolicy:
可选策略有:
LRU(最近最少使用,默认策略)、
FIFO(先进先出)、
LFU(最少访问次数)。
FIFO,first in first out,这个是大家最熟的,先进先出。
LFU, Less Frequently Used,就是上面例子中使用的策略,直白一点就是讲一直以 来最少被使用的。如上面所讲,缓存的元素有一个hit属性,hit值最小的将会被清出缓存。 L'
RU,Least Recently Used,最近最少使用的,缓存的元素有一个时间戳,当缓存容 量满了,而又需要腾出地方来缓存新的元素的时候,那么现有缓存元素中时间戳离当前时间最远的 元素将被清出缓存。 -->
</ehcache>
- 使用三方缓存工具:在 mapper 映射文件中修改。
<!-- type:指定缓存类型,不指定就是使用 mybatis 的缓存-->
<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
8、Mybatis 分页插件
导入依赖:
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.3.3</version>
</dependency>
设置 mybatis 插件:
<plugins>
<!-- 设置分页插件拦截器-->
<plugin interceptor="com.github.pagehelper.PageInterceptor"/>
</plugins>
使用方式:
@Test
public void test6(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
// 开启分页,在下一个查询语句会进行分页拦截,参数一:页码,参数二:一页数量
PageHelper.startPage(1,5);
List<User> users2 = mapper.selectAll();
// 参数是查询后的 list 结果
PageInfo<User> pageInfo = new PageInfo<>(users2);
System.out.println(pageInfo.getList());
}