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>

相關文章
相關標籤/搜索