0、MyBatis简介
1)MyBatis是Apache的一个开源项目iBatis, 2010年6月这个项目由Apache Software Foundation 迁移到了Google Code,随着开发团队转投Google Code旗下, iBatis3.x 正式更名为MyBatis ,代码于2013年11月迁移到Github
2)iBatis一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。 iBatis 提供的持久层框架包括SQL Maps和Data Access Objects(DAO)
下载网址
https://github.com/mybatis/mybatis-3/
为什么要使用MyBatis – 现有持久化技术的对比
- JDBC
- SQL夹在Java代码块里,耦合度高导致硬编码内伤
- 维护不易且实际开发需求中sql有变化,频繁修改的情况多见
2.Hibernate和JPA
- 长难复杂SQL,对于Hibernate而言处理也不容易
- 内部自动生产的SQL,不容易做特殊优化
- 基于全映射的全自动框架,大量字段的POJO进行部分映射时比较困难。导致数据库性能下降
3.MyBatis
- 对开发人员而言,核心sql还是需要自己优化
- sql和java编码分开,功能边界清晰,一个专注业务、一个专注数据
1.MyBatis HelloWorld
1.导入MyBatis框架的jar包、Mysql驱动包、log4j的jar包
- myBatis-3.4.1.jar
- mysql-connector-java-5.1.37-bin.jar
- log4j.jar
2.导入log4j.xml配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
<param name="Encoding" value="UTF-8" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%-5p %d{MM-dd HH:mm:ss,SSS} %m (%F:%L) \n" />
</layout>
</appender>
<logger name="java.sql">
<level value="debug" />
</logger>
<logger name="org.apache.ibatis">
<level value="info" />
</logger>
<root>
<level value="debug" />
<appender-ref ref="STDOUT" />
</root>
</log4j:configuration>
3.创建测试表
-- 创建库
CREATE DATABASE test_mybatis;
-- 使用库
USE test_mybatis;
-- 创建表
CREATE TABLE tbl_employee(
id INT(11) PRIMARY KEY AUTO_INCREMENT,
last_name VARCHAR(50),
email VARCHAR(50),
gender CHAR(1)
);
4.创建javaBean
public class Employee {
private Integer id ;
private String lastName;
private String email ;
private String gender ;
public Integer getId() {
return id;
}
//...生成get、set 、toString
}
5.创建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.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/mybatis_1129" />
<property name="username" value="root" />
<property name="password" value="123456" />
</dataSource>
</environment>
</environments>
<!-- 引入SQL映射文件,Mapper映射文件 -->
<mappers>
<mapper resource="EmployeeMapper.xml" />
</mappers>
</configuration>
6.创建Mybatis的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="suibian">
<select id="selectEmployee" resultType="com.hbuas.myabtis.helloWorld.Employee">
select id ,last_name lastName ,email ,gender from tbl_employee where id = #{id}
<!-- select * from tbl_employee where id = #{id} -->
</select>
</mapper>
7.编写测试类
@Test
public void test() throws Exception {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory =
new SqlSessionFactoryBuilder().build(inputStream);
System.out.println(sqlSessionFactory);
SqlSession session = sqlSessionFactory.openSession();
try {
Employee employee =
session.selectOne("suibian.selectEmployee", 1001);
System.out.println(employee);
} finally {
session.close();
}
}
Mapper接口开发MyBatis HelloWorld
使用mapper接口开发是秉承Mybatis倡导的面向接口编程
1.编写Mapper接口,实现两个绑定:
- 接口全限定名要和映射文件的namespace保持一致
- 接口中方法名和SQL语句的ID保持一致
public interface EmployeeMapper {
public Employee getEmployeeById(Integer id );
}
3.编写测试类
获取Mybatis操作数据库的会话对象SqlSession,通过getMapper()获取接口的动态代理实现类
@Test
public void test() throws Exception{
String resource = "mybatis-config.xml";
InputStream inputStream =
Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory =
new SqlSessionFactoryBuilder()
.build(inputStream);
SqlSession session =
sqlSessionFactory.openSession();
try {
//Mapper接口:获取Mapper接口的 代理实现类对象
EmployeeMapper mapper =
session.getMapper(EmployeeMapper.class);
Employee employee =
mapper.getEmployeeById(1006);
System.out.println(employee);
} finally {
session.close();
}
}
3.Mybatis配置文件
MyBatis 的配置文件包含了影响 MyBatis 行为甚深的设置(settings)和属性(properties)信息。
配置文件结构如下:
configuration 配置 |
属性信息严格按照上面顺序配置。
properties属性
- 可外部配置且可动态替换,既可以在典型的 Java 属性文件中配置,亦可通过 properties 元素的子元素来配置
<properties> <property name="driver" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/test_mybatis" /> <property name="username" value="root" /> <property name="password" value="1234" /> </properties>
properties的作用并不单单是这样,你可以创建一个资源文件,名为jdbc.properties的文件,将四个连接字符串的数据在资源文件中通过键值 对(key=value)的方式放置,不要任何符号,一条占一行
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis_1129
jdbc.username=root
jdbc.password=1234
<!--
properties: 引入外部的属性文件
resource: 从类路径下引入属性文件
url: 引入网络路径或者是磁盘路径下的属性文件
-->
<properties resource="db.properties" ></properties>
<environments default="oracle">
<environment id="mysql">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}" />
<property name="username"
value="${jdbc.username}" />
<property name="password"
value="${jdbc.password}" />
</dataSource>
</environment>
</environments>
settings设置
- 这是 MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为。
- 包含如下的setting设置:
<settings>
<setting name="cacheEnabled" value="true"/>
<setting name="lazyLoadingEnabled" value="true"/>开启延迟加载
<setting name="multipleResultSetsEnabled" value="true"/>
<setting name="useColumnLabel" value="true"/>
<setting name="useGeneratedKeys" value="false"/>
<setting name="autoMappingBehavior" value="PARTIAL"/>
<setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
<setting name="defaultExecutorType" value="SIMPLE"/>
<setting name="defaultStatementTimeout" value="25"/>
<setting name="defaultFetchSize" value="100"/>
<setting name="safeRowBoundsEnabled" value="false"/>
<setting name="mapUnderscoreToCamelCase" value="false"/>将下划线映射成驼峰
<setting name="localCacheScope" value="SESSION"/>
<setting name="jdbcTypeForNull" value="OTHER"/>
<setting name="lazyLoadTriggerMethods"
value="equals,clone,hashCode,toString"/>
</settings>
typeAliases
1.类型别名是为 Java 类型设置一个短的名字,可以方便我们引用某个类。
<typeAliases>
<typeAlias type="com.hbuas.mybatis.beans.Employee" alias="emp"/>
</typeAliases>
alias属性可以不写,不写默认就是类名切不区分大小写。
2.类很多的情况下,可以批量设置别名这个包下的每一个类创建一个默认的别名,就是简单类名小写
<typeAliases>
<package name="com.hbuas.mybatis.beans"/>
</typeAliases>
environments 环境配置
- MyBatis可以配置多种环境,比如开发、测试和生产环境需要有不同的配置
- 每种环境使用一个environment标签进行配置并指定唯一标识符
- 可以通过environments标签中的default属性指定一个环境的标识符来快速的切换环境
- environment-指定具体环境
- id:指定当前环境的唯一标识
- transactionManager、和dataSource都必须有
<environments default="oracle">
<environment id="mysql">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</dataSource>
</environment>
<environment id="oracle">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${orcl.driver}" />
<property name="url" value="${orcl.url}" />
<property name="username" value="${orcl.username}" />
<property name="password" value="${orcl.password}" />
</dataSource>
</environment>
</environments>
4.MyBatis 映射文件
- MyBatis 的真正强大在于它的映射语句,也是它的魔力所在。由于它的异常强大,映射器的 XML 文件就显得相对简单。如果拿它跟具有相同功能的 JDBC 代码进行对比,你会立即发现省掉了将近 95% 的代码。MyBatis 就是针对 SQL 构建的,并且比普通的方法做的更好。
- SQL 映射文件有很少的几个顶级元素(按照它们应该被定义的顺序):
cache – 给定命名空间的缓存配置。
cache-ref – 其他命名空间缓存配置的引用。
resultMap – 是最复杂也是最强大的元素,用来描述如何从数据库结果集中来加载对象。
parameterMap – 已废弃!老式风格的参数映射。内联参数是首选,这个元素可能在将来被移除,这里不会记录。
sql – 可被其他语句引用的可重用语句块。
insert – 映射插入语句
update – 映射更新语句
delete – 映射删除语句
select – 映射查询语
使用insert|update|delete|select完成CRUD
- Mapper接口方法
public interface EmpMapper { //根据eid查询一个员工信息 Emp getEmpByEid(String eid); //获取所有的员工信息 List<Emp> getAllEmp(); //添加员工信息 void addEmp(Emp emp); //修改员工信息 void updateEmp(Emp emp); //删除员工信息 Boolean deleteEmp(String eid); }
- Mapper映射文件
<mapper namespace="com.hbuas.mapper.EmpMapper"> <!-- Emp getEmpByEid(String eid); --> <select id="getEmpByEid" resultType="Emp"> select eid,ename,age,sex from emp where eid = #{eid} </select> <!-- List<Emp> getAllEmp(); --> <select id="getAllEmp" resultType="Emp"> select eid,ename,age,sex from emp </select> <!-- void addEmp(Emp emp); --> <insert id="addEmp"> insert into emp values(null,#{ename},#{age},#{sex}) </insert> <!-- void updateEmp(Emp emp); --> <update id="updateEmp"> update emp set ename = #{ename}, age = #{age}, sex = #{sex} where eid = #{eid} </update> <!-- void deleteEmp(String eid); --> <delete id="deleteEmp"> delete from emp where eid = #{eid} </delete> </mapper>
主键生成方式、获取主键值
获取主键值
- 若数据库支持自动生成主键的字段(比如 MySQL 和 SQL Server),则可以设置 useGeneratedKeys=”true”,然后再把 keyProperty 设置到目标属性上。
<insert id="insertEmployee" parameterType="com.hbuas.mybatis.beans.Employee" databaseId="mysql" useGeneratedKeys="true" keyProperty="id"> insert into tbl_employee(last_name,email,gender) values(#{lastName},#{email},#{gender}) </insert>
- 而对于不支持自增型主键的数据库(例如 Oracle),则可以使用 selectKey 子元素:selectKey 元素将会首先运行,id 会被设置,然后插入语句会被调用
<insert id="insertEmployee" parameterType="com.atguigu.mybatis.beans.Employee" databaseId="oracle"> <selectKey order="BEFORE" keyProperty="id" resultType="integer"> select employee_seq.nextval from dual </selectKey> insert into orcl_employee(id,last_name,email,gender) values(#{id},#{lastName},#{email},#{gender}) </insert>
参数传递
myBatis获取参数值的两种方式:
- ${}
- insert into emp values(null,admin,23,男)
- Statement:必须使用字符串拼接的方式操作SQL
- #{}
- insert into emp values(null,?,?,?)
- PrepareStatement:可以使用通配符操作SQL;
参数传递的方式
1.单个普通类型参数:可以接受基本类型,包装类型,字符串类型等。
- #{}:可以以任意的名字获取参数值
- ${}:只能以${value}、${_parameter}获取
2.多个参数
任意多个参数,都会被MyBatis重新包装成一个Map传入。Map的key是param1,param2,或者0,1…,值就是参数的值
#{}:#{0}、#{1}、#{param1}、#{param2}
${}:${value}、${ param2 },但是要注意${}的单引号问题
3.命名参数
为参数使用@Param起一个名字,MyBatis就会将这些参数封装进map中,key就是我们自己指定的名字。#{},${}都可以通过健名获取值,注意单引号问题。
4.POJO
当这些参数属于我们业务POJO时,我们直接传递POJO属性名获取值,但是注意${}单引号问题。
5.Map
我们也可以封装多个参数为map,直接传递
6.Collection/Array
会被MyBatis封装成一个map传入, List以list为键,Array以array为键
自动映射和自定义映射
- resultType自动映射
- 默认是开启自动映射的功能。唯一的要求是结果集列名和javaBean属性名一致。
- 如果autoMappingBehavior设置为null则会取消自动映射
- resultMap自定义映射
<!--
<resultMap>:自定义映射,处理复杂的表关系
<id column="eid" property="eid"/>
<id>:设置主键的映射关系,column设置字段名,property设置属性名
<result column="ename" property="ename"/>
<result>:设置非主键的映射关系,column设置字段名,property设置属性名
-->
<!-- 此种方式用的比较少-->
<resultMap type="Emp" id="empMap">
<id column="eid" property="eid"/>
<result column="ename" property="ename"/>
<result column="age" property="age"/>
<result column="sex" property="sex"/>
<result column="did" property="dept.did"/>
<result column="dname" property="dept.dname"/>
</resultMap>
<!-- List<Emp> getAllEmp(); -->
<select id="getAllEmp" resultMap="empMap">
select e.eid,e.ename,e.age,e.sex,e.did,d.dname from emp e left join dept d on e.did = d.did
</select>
association
以级联属性的方式封装对象.
<resultMap type="Emp" id="empMap">
<id column="eid" property="eid"/>
<result column="ename" property="ename"/>
<result column="age" property="age"/>
<result column="sex" property="sex"/>
<association property="dept" javaType="Dept">
<id column="did" property="did"/>
<result column="dname" property="dname"/>
</association>
</resultMap>
association 分步查询
- 实际的开发中,对于每个实体类都应该有具体的增删改查方法,也就是DAO层, 因此对于查询员工信息并且将对应的部门信息也查询出来的需求,就可以通过分步的方式完成查询。
- 先通过员工的id查询员工信息
- 再通过查询出来的员工信息中的外键(部门id)查询对应的部门信息.
<select id="getEmployeeAndDeptStep" resultMap="myEmpAndDeptStep">
select id, last_name, email,gender,d_id from tbl_employee where id =#{id}
</select>
<resultMap type="com.hbuas.mybatis.beans.Employee" id="myEmpAndDeptStep">
<id column="id" property="id" />
<result column="last_name" property="lastName"/>
<result column="email" property="email"/>
<result column="gender" property="gender"/>
<association property="dept"
select="com.hbuas.mybatis.dao.DepartmentMapper.getDeptById"
column="d_id" fetchType="eager">
</association>
</resultMap>
- 在分步查询的基础上,可以使用延迟加载来提升查询的效率,只需要在全局的
Settings中进行如下的配置:
<!-- 开启延迟加载 -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 设置加载的数据是按需还是全部 -->
<setting name="aggressiveLazyLoading" value="false"/>
collection
专门用来处理一对多和多对多的关系
- POJO中的属性可能会是一个集合对象,我们可以使用联合查询,并以级联属性的方式封装对象.使用collection标签定义对象的封装规则
<resultMap type="Dept" id="deptMap"> <id column="did" property="did"/> <result column="dname" property="dname"/> <!-- <collection>:处理一对多和多对多的关系 ofType:指集合中的类型,不需要指定javaType --> <collection property="emps" ofType="Emp"> <id column="eid" property="eid"/> <result column="ename" property="ename"/> <result column="age" property="age"/> <result column="sex" property="sex"/> </collection> </resultMap>
collection 分步查询
- 实际的开发中,对于每个实体类都应该有具体的增删改查方法,也就是DAO层, 因此
对于查询部门信息并且将对应的所有的员工信息也查询出来的需求,就可以通过分步的方式完成查询。
- 先通过部门的id查询部门信息
- 再通过部门id作为员工的外键查询对应的部门信息.
<!-- List<Emp> getEmpListByDid(String did); -->
<select id="getEmpListByDid" resultType="Emp">
select eid,ename,age,sex from emp where did = #{did}
</select>
<resultMap type="Dept" id="deptMapStep">
<id column="did" property="did"/>
<result column="dname" property="dname"/>
<collection property="emps" select="com.hbuas.mapper.EmpDeptMapper.getEmpListByDid" column="{did=did}" fetchType="eager"></collection>
</resultMap>
<!-- Dept getOnlyDeptByDid(String did); -->
<select id="getOnlyDeptByDid" resultMap="deptMapStep">
select did,dname from dept where did = #{did}
</select>
1.在<association> 和<collection>标签中都可以设置fetchType,指定本次查询是否要使用延迟加载。默认为 fetchType=”lazy” ,如果本次的查询不想使用延迟加载,则可设置为fetchType=”eager”.
2.fetchType可以灵活的设置查询是否需要使用延迟加载,而不需要因为某个查询不想使用延迟加载将全局的延迟加载设置关闭.
5.MyBatis动态SQL
MyBatis动态SQL简介
- 动态 SQL是MyBatis强大特性之一。极大的简化我们拼装SQL的操作
- 动态 SQL 元素和使用 JSTL 或其他类似基于 XML 的文本处理器相似
- MyBatis 采用功能强大的基于 OGNL 的表达式来简化操作
if where
- If用于完成简单的判断.
- Where用于解决SQL语句中where关键字以及条件中第一个and或者or的问题
<select id="getEmpListByMoreTJ1" resultType="Emp">
select eid,ename,age,sex,did from emp
<where>
<if test="eid != null">
and eid = #{eid}
</if>
<if test="ename != null and ename != ''">
and ename = #{ename}
</if>
<if test="age != null">
and age = #{age}
</if>
<if test="sex == 1 or sex == 0">
and sex = #{sex}
</if>
</where>
</select>
trim
- Trim 可以在条件判断完的SQL语句前后 添加或者去掉指定的字符
- prefix: 在操作的SQL语句前加入某些内容
- prefixOverrides: 把操作的SQL语句前的某系内容去掉
- suffix: 在操作的SQL语句前加入某些内容
- suffixOverrides: 把操作的SQL语句前的某系内容去掉
<select id="getEmpListByMoreTJ1" resultType="Emp">
select eid,ename,age,sex,did from emp
<trim prefix="where" suffixOverrides="and">
<if test="eid != null">
eid = #{eid} and
</if>
<if test="ename != null and ename != ''">
ename = #{ename}and
</if>
<if test="age != null">
age = #{age}and
</if>
<if test="sex == 1 or sex == 0">
sex = #{sex}
</if>
</where>
</select>
set
set 主要是用于解决修改操作中SQL语句中可能多出逗号的问题
<update id="updateEmpByConditionSet">
update tbl_employee
<set>
<if test="lastName!=null && lastName!=""">
last_name = #{lastName},
</if>
<if test="email!=null and email.trim()!=''">
email = #{email} ,
</if>
<if test=""m".equals(gender) or "f".equals(gender)">
gender = #{gender}
</if>
</set>
where id =#{id}
</update>
choose(when、otherwise)
choose 主要是用于分支判断,类似于java中的switch case,只会满足所有分支中的一个
<select id="getEmpsByConditionChoose" resultType="com.hbuas.mybatis.beans.Employee">
select id ,last_name, email,gender from tbl_employee
<where>
<choose>
<when test="id!=null">
id = #{id}
</when>
<when test="lastName!=null">
last_name = #{lastName}
</when>
<when test="email!=null">
email = #{email}
</when>
<otherwise>
gender = 'm'
</otherwise>
</choose>
</where>
</select>
foreach
<!--
<foreach collection="" item="" close="" open="" separator="" index=""></foreach>
对一个数组或集合进行遍历
collection:指定要遍历的集合或数组
item:设置别名
close:设置循环体的结束内容
open:设置循环体的开始内容
separator:设置每一次循环之间的分隔符
index:若遍历的是list,index代表下标;若遍历的是map,index代表键
-->
<delete id="deleteMoreByList">
delete from emp where eid in
<foreach collection="eids" item="eid" separator="," open="(" close=")">
#{eid}
</foreach>
</delete>
sql
sql 标签是用于抽取可重用的sql片段,将相同的,使用频繁的SQL片段抽取出来,单独定义,方便多次引用.
<!--
<sql id=""></sql>:设置一段SQL片段,即公共SQL,可以被当前映射文件中所有的SQL语句所访问
<include refid="empColumns"></include>:访问某个SQL片段
-->
<sql id="empColumns">select eid,ename,age,sex,did from emp </sql>
<select id="getEmpByEid" resultType="Emp">
<include refid="empColumns"></include> where eid = #{eid}
</select>
6.MyBatis 缓存机制
MyBatis 包含一个非常强大的查询缓存特性,它可以非常方便地配置和定制。缓存可以极大的提升查询效率,MyBatis系统中默认定义了两级缓存(一级缓存、二级缓存)默认情况下,只有一级缓存(SqlSession级别的缓存,也称为本地缓存)开启。
- 二级缓存需要手动开启和配置,他是基于namespace级别的缓存。
- 为了提高扩展性。MyBatis定义了缓存接口Cache。我们可以通过实现Cache接口来自定义二级缓存
一级缓存的使用
/**
mybatis中的一级缓存默认开启,是SqlSession级别的
即同一个SqlSession对于一个sql语句,执行之后就会存储在缓存中,下次执行相同的sql,直接从缓存中取
一级缓存失效的情况:
* 不同的SqlSession对应不同的一级缓存
* 同一个SqlSession但是查询条件不同
* 同一个SqlSession两次查询期间执行了任何一次增删改操作,会自动将缓存清空
* 同一个SqlSession两次查询期间手动清空了缓存
*/
二级缓存的使用
/**
* mybatis的二级缓存默认不开启,需要设置:
* 1、在核心配置文件<settings>中,加入配置:<setting name="cacheEnabled" value="true"/>
* 2、需要使用二级缓存的映射文件处使用cache配置缓存<cache />
* 3、注意:POJO需要实现Serializable接口
* 注意:二级缓存在 SqlSession 关闭或提交之后才会生效
* 1)全局setting的cacheEnable:
配置二级缓存的开关,一级缓存一直是打开的
* 2)select标签的useCache属性:
配置这个select是否使用二级缓存。一级缓存一直是使用的
* 3)sql标签的flushCache属性:
增删改默认flushCache=true。sql执行以后,会同时清空一级和二级缓存。
查询默认 flushCache=false。
* 4)sqlSession.clearCache():只是用来清除一级缓存
*/
二级缓存相关的属性
- eviction=“FIFO”:缓存回收策略:
LRU – 最近最少使用的:移除最长时间不被使用的对象。
FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。
WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。
默认的是 LRU。
- flushInterval:刷新间隔,单位毫秒
默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新
- size:引用数目,正整数
代表缓存最多可以存储多少个对象,太大容易导致内存溢出
- readOnly:只读,true/false
true:只读缓存;会给所有调用者返回缓存对象的相同实例。因此这些对象不能被修改。这提供了很重要的性能优势。
false:读写缓存;会返回缓存对象的拷贝(通过序列化)。这会慢一些,但是安全,因此默认是 false。
缓存的相关属性设置
- 全局setting的cacheEnable:配置二级缓存的开关,一级缓存一直是打开的。
- select标签useCache属性:配置这个select是否使用二级缓存。一级缓存一直是使用的
- sql标签的flushCache属性:增删改默认flushCache=true。sql执行以后,会同时清空一级和二级缓存。查询默认 flushCache=false。
- sqlSession.clearCache():只是用来清除一级缓存。
整合第三方缓存
为了提高扩展性。MyBatis定义了缓存接口Cache。我们可以通过实现Cache接口来自定义二级缓存
EhCache 是一个纯Java的进程内缓存框架,具有快速、精干等特点,是Hibernate中默认的CacheProvider
整合EhCache缓存的步骤
1.导入ehcache包,以及整合包,日志包
- ehcache-core-2.6.8.jar
- mybatis-ehcache-1.0.3.jar
- slf4j-api-1.6.1.jar、slf4j-log4j12-1.6.2.jar
2.编写ehcache.xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
<!-- 磁盘保存路径 -->
<diskStore path="D:\hbuas\ehcache" />
<defaultCache
maxElementsInMemory="1000"
maxElementsOnDisk="10000000"
eternal="false"
overflowToDisk="true"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU">
</defaultCache>
</ehcache>
<!--
属性说明:
l diskStore:指定数据在磁盘中的存储位置。
l defaultCache:当借助CacheManager.add("demoCache")创建Cache时,EhCache便会采用<defalutCache/>指定的的管理策略
以下属性是必须的:
l maxElementsInMemory - 在内存中缓存的element的最大数目
l maxElementsOnDisk - 在磁盘上缓存的element的最大数目,若是0表示无穷大
l eternal - 设定缓存的elements是否永远不过期。如果为true,则缓存的数据始终有效,如果为false那么还要根据timeToIdleSeconds,timeToLiveSeconds判断
l overflowToDisk - 设定当内存缓存溢出的时候是否将过期的element缓存到磁盘上
以下属性是可选的:
l timeToIdleSeconds - 当缓存在EhCache中的数据前后两次访问的时间超过timeToIdleSeconds的属性取值时,这些数据便会删除,默认值是0,也就是可闲置时间无穷大
l timeToLiveSeconds - 缓存element的有效生命期,默认是0.,也就是element存活时间无穷大
diskSpoolBufferSizeMB 这个参数设置DiskStore(磁盘缓存)的缓存区大小.默认是30MB.每个Cache都应该有自己的一个缓冲区.
l diskPersistent - 在VM重启的时候是否启用磁盘保存EhCache中的数据,默认是false。
l diskExpiryThreadIntervalSeconds - 磁盘缓存的清理线程运行间隔,默认是120秒。每个120s,相应的线程会进行一次EhCache中数据的清理工作
l memoryStoreEvictionPolicy - 当内存缓存达到最大,有新的element加入的时候, 移除缓存中element的策略。默认是LRU(最近最少使用),可选的有LFU(最不常使用)和FIFO(先进先出)
-->
3.配置cache标签
<cache type="org.mybatis.caches.ehcache.EhcacheCache"></cache>
来源:oschina
链接:https://my.oschina.net/u/4152684/blog/3166289