MyBatis就是这么简单

0、MyBatis简介

 1MyBatisApache的一个开源项目iBatis, 20106月这个项目由Apache Software      Foundation 迁移到了Google Code,随着开发团队转投Google Code旗下, iBatis3.x   正式改名为MyBatis ,代码于201311月迁移到Githubjava

 2iBatis一词来源于“internet”“abatis”的组合,是一个基于Java的持久层框架。 iBatis  提供的持久层框架包括SQL MapsData Access ObjectsDAOmysql

下载网址git

         https://github.com/mybatis/mybatis-3/github

为何要使用MyBatis – 现有持久化技术的对比

  1. JDBC
  • SQL夹在Java代码块里,耦合度高致使硬编码内伤
  • 维护不易且实际开发需求中sql有变化,频繁修改的状况多见

2.HibernateJPAsql

  • 长难复杂SQL,对于Hibernate而言处理也不容易
  • 内部自动生产的SQL,不容易作特殊优化
  • 基于全映射的全自动框架,大量字段的POJO进行部分映射时比较困难。致使数据库性能降低

3.MyBatis数据库

  • 对开发人员而言,核心sql仍是须要本身优化
  • sqljava编码分开,功能边界清晰,一个专一业务、一个专一数据

1.MyBatis HelloWorld

1.导入MyBatis框架的jar包、Mysql驱动包、log4jjarapache

  • 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.建立测试表api

-- 建立库
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 属性
    settings 设置
    typeAliases 类型命名
    typeHandlers 类型处理器
    objectFactory 对象工厂
    plugins 插件
    environments 环境
        environment 环境变量

           transactionManager 事务管理器
           dataSource 数据源
    databaseIdProvider 数据库厂商标识
    mappers 映射器

 

属性信息严格按照上面顺序配置。

properties属性

  1. 可外部配置且可动态替换,既能够在典型的 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设置

  1. 这是 MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为。
  2. 包含以下的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 环境配置

  1. MyBatis能够配置多种环境,好比开发、测试和生产环境须要有不一样的配置
  2. 每种环境使用一个environment标签进行配置并指定惟一标识符
  3. 能够经过environments标签中的default属性指定一个环境的标识符来快速的切换环境
  4. 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 映射文件

  1. MyBatis 的真正强大在于它的映射语句,也是它的魔力所在。因为它的异常强大,映射器的 XML 文件就显得相对简单。若是拿它跟具备相同功能的 JDBC 代码进行对比,你会当即发现省掉了将近 95% 的代码。MyBatis 就是针对 SQL 构建的,而且比普通的方法作的更好。
  2. SQL 映射文件有不多的几个顶级元素(按照它们应该被定义的顺序):

cache – 给定命名空间的缓存配置。

cache-ref – 其余命名空间缓存配置的引用。

resultMap – 是最复杂也是最强大的元素,用来描述如何从数据库结果集中来加载对象。

parameterMap – 已废弃!老式风格的参数映射。内联参数是首选,这个元素可能在未来被移除,这里不会记录。

sql – 可被其余语句引用的可重用语句块。

insert – 映射插入语句

update – 映射更新语句

delete – 映射删除语句

select – 映射查询语

使用insert|update|delete|select完成CRUD

  1. Mapper接口方法
    public interface EmpMapper {
    
    	//根据eid查询一个员工信息
    	Emp getEmpByEid(String eid);
    	//获取全部的员工信息
    	List<Emp> getAllEmp();
    	//添加员工信息
    	void addEmp(Emp emp);
    	//修改员工信息
    	void updateEmp(Emp emp);
    	//删除员工信息
    	Boolean deleteEmp(String eid);
    	
    }
  2. 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>

    主键生成方式、获取主键值

获取主键值

  1. 若数据库支持自动生成主键的字段(好比 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>
  2. 而对于不支持自增型主键的数据库(例如 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传入。Mapkeyparam1param2,或者01…,值就是参数的值

#{}:#{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 分步查询

  1. 实际的开发中,对于每一个实体类都应该有具体的增删改查方法,也就是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

专门用来处理一对多和多对多的关系

  1. 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 分步查询

  1. 实际的开发中,对于每一个实体类都应该有具体的增删改查方法,也就是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简介

  1. 动态 SQLMyBatis强大特性之一。极大的简化咱们拼装SQL的操做
  2. 动态 SQL 元素和使用 JSTL 或其余相似基于 XML 的文本处理器类似
  3. MyBatis 采用功能强大的基于 OGNL 的表达式来简化操做

if  where

  1. If用于完成简单的判断.
  2. 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

  1. 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 &amp;&amp; lastName!=&quot;&quot;">
				 last_name = #{lastName},
			</if>
			<if test="email!=null and email.trim()!=''">
				 email = #{email} ,
			</if>
			<if test="&quot;m&quot;.equals(gender) or &quot;f&quot;.equals(gender)">
				gender = #{gender} 
			</if>
		</set>
		 where id =#{id}
</update>

choose(whenotherwise)

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级别的缓存,也称为本地缓存)开启。

  1. 二级缓存须要手动开启和配置,他是基于namespace级别的缓存。
  2. 为了提升扩展性。MyBatis定义了缓存接口Cache。咱们能够经过实现Cache接口来自定义二级缓存

一级缓存的使用

/**
mybatis中的一级缓存默认开启,是SqlSession级别的
	即同一个SqlSession对于一个sql语句,执行以后就会存储在缓存中,下次执行相同的sql,直接从缓存中取
          

  一级缓存失效的状况:
		 * 不一样的SqlSession对应不一样的一级缓存
		 * 同一个SqlSession可是查询条件不一样
		 * 同一个SqlSession两次查询期间执行了任何一次增删改操做,会自动将缓存清空
		 * 同一个SqlSession两次查询期间手动清空了缓存
*/

二级缓存的使用

/**
 * mybatis的二级缓存默认不开启,须要设置:
         * 一、在核心配置文件<settings>中,加入配置:<setting name="cacheEnabled" value="true"/>
         * 二、须要使用二级缓存的映射文件处使用cache配置缓存<cache />
         * 三、注意: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

缓存的相关属性设置

  1. 全局settingcacheEnable配置二级缓存的开关,一级缓存一直是打开的。
  2. select标签useCache属性:配置这个select是否使用二级缓存。一级缓存一直是使用的
  3. sql标签的flushCache属性:增删改默认flushCache=truesql执行之后,会同时清空一级和二级缓存。查询默认 flushCache=false
  4. 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.jarslf4j-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>

相关文章
相关标签/搜索