1. 程式人生 > >框架學習--mybatis--01

框架學習--mybatis--01

一、簡介

1、概念

  • mybatis 是一個半自動輕量級的一個 orm 框架

2、作用

  • 將 java 與 sql 分離,解決了 jdbc 的硬編碼問題,方便 sql 的修改;
  • sql 由開發人員控制,更加方便 sql 的調優;

3、快速開始

(1)原始方法

  • 建一個全域性配置檔案,裡面是資料來源等執行環境的資訊;
  • 建立一個sql 的對映檔案,並將這個檔案註冊到全域性的配置中;
  • 根據全域性的配置檔案獲得一個 sqlsessionfactory;
  • 通過 factory 獲得 sqlsession(非執行緒安全),一個sqlsession 就是和資料庫的一次會話,用完需要關閉;
  • sqlsession通過 sql 的唯一識別符號呼叫方法執行;
  • 注意資料庫的欄位名和bean的欄位名要相同才能順利對映;

(2)介面式程式設計

  • 定義一個介面,介面中定義操作資料庫的方法;
  • 將介面和sql的對映檔案繫結:xml的namespace是介面全限定名,sql的id是介面中的方法名;
  • 在 java 程式中通過session獲得藉口的實現類(代理物件)物件;
  • 通過物件呼叫方法執行相應的sql;

 

二、配置檔案

1、全域性配置檔案

(1)xml 中引入 dtd 約束

(2)properties標籤:url引入網路或者磁碟的資源;resource引入 classpath 下的資源;

(3)settings標籤:設定一些mybatis執行時的重要引數

(4)typeAliases標籤:就是給 java 類起別名用的

  • 別名不分大小寫;
  • 可以單獨起也可以批量起;
  • 預設別名就是類名;
  • 也可以使用註解來起別名(@alias);
  • java 中的基本資料型別和一些常用的類已經取好了別名(基本型別就是前面加 _ ;引用型別就是原類名)

(5)typeHandlers標籤:

  • 就是處理 java 型別和資料庫型別的轉換的;
  • 常用的型別 mybatis 都給預設處理了,不用我們自己去做;
  • 當然是支援自定義的了;

(6)plugins標籤:

作用就是攔截四大物件,改變他們的預設行為

(7)environments標籤:

  • 用來配置環境的,可以配置多個環境,在default屬性裡可以指定預設的環境;
  • 每個環境都應包含:transactionManager 和 dataSource

(8)databaseIdProvider標籤:

  • 為mybatis提供多資料庫廠商的支援;
  • 廠商標識在資料庫的驅動裡;
  • 標籤內通過property標籤指定資料庫的別名;
  • 在相應的sql語句的標籤上用databaseId引入資料庫的別名;
  • 注意:主配置檔案裡的標籤的書寫的順序是有要求的,databaseIdProvider應該寫在envir 和 mapper 之間;

(9)mappers標籤:

  • 作用就是註冊 sql 對映;
  • 裡面具體的 mapper 的屬性有三種寫法:
  • resource:classpath 路徑下;
  • url:網路資源或者磁碟資源;
  • class:指定對應的對映的介面(條件是必須同包同名);
  • 批量的註冊直接用package 標籤(條件是必須同包同名);
<?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>
	<properties resource="conf/dbconfig.properties"></properties>
	
	<!-- <settings>
		<setting name="" value="" />
	</settings>

	<typeAliases>
		單獨起別名
		<typeAlias type="" alias="" />
		批量起別名
		<package name="" />
	</typeAliases>

	<typeHandlers>
		<typeHandler handler="" />
	</typeHandlers>

	<plugins>
		<plugin interceptor=""></plugin>
	</plugins>	 -->
	
	<environments default="development">
		<!-- <environment id="test">
			<transactionManager type=""></transactionManager>
			<dataSource type=""></dataSource>
		</environment> -->
		<environment id="development">
			<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>
	
	<databaseIdProvider type="DB_VENDOR">
		<property name="Oracle" value="oracle" />
		<property name="MySQL" value="mysql" />
	</databaseIdProvider>
	
	<mappers>
		<mapper resource="conf/TuserMapper.xml" />
	</mappers>
</configuration>

2、sql對映檔案概述

(1)增刪改測試

  • int、long 和 boolean 型別的返回值我們可以直接用;
  • 增刪改後一定要 commit;

(2)資料插入獲得自增主鍵

  • mysql:支援自增主鍵
  1. useGeneratedKeys 和 keyProperty 屬性配合使用即可獲取到自增主鍵的值
  • oracle:不支援自增主鍵,靠序列來完成
  1. 在要執行的sql前用 selectKey 標籤來實現
  2. 相關的三個屬性分別是 keyProperty、resultType 和 order;
  3. 有兩種寫法分別是 order 的屬性值為 before 和 after;通常使用 before

3、對映檔案的引數處理

(1)單個引數

  • 單個引數可以在 #{}中隨意寫;

(2)多個引數

  • 多個引數預設在其中寫 param1 和 param2 等;也可以用註解@param 指定名稱;多個引數本質是封裝在一個map中;
  • 業務相關的資料直接封裝在 pojo 中;
  • 關聯性不高且使用的頻率不高的話的可以放在一個map裡;在map 裡可以隨意指定鍵名;
  • 同時多個引數如果使用的頻率很高的話還可以封裝為一個 TO 物件;
  • 集合和陣列的特殊處理:引數可以寫 collection、list 和 array;

(3)引數處理原始碼分析

  • 引數封裝成map 的過程:總結起來就是引數多的時候就封裝成 map 集合,有@param註解的引數的鍵值就是指定的值,否則就是預設的;

(4)關於 #{} 和 ${}兩種取值的方法:

  • #{}是以預編譯的形式來取引數的值的,可以防注入;而${}是直接拼接的;
  • 大多數的情況採用 #{},但在原生的 jdbc 不支援佔位符的地方可以使用 ${},比如order by ${age};
  • #{}進行引數設定的時候可以指定一些規則,比如:#{email,jdbcType.null},mybatis自動將 null值對映為jdbc的other型別,這個型別oracle不支援會報錯;

4、對映檔案的select 元素

(1)resultType

  • resultType的作用就是指定結果集的封裝的規則;
  • 結果集封裝為 list型別直接寫 list裡資料型別即可;
  • 封裝為 map 單條記錄直接寫 map 的別名;多條記錄寫pojo 的型別(map的值是pojo),map的鍵值在相應的方法上面用註解@mapKey來指定pojo中的屬性;

(2)resultMap(關聯查詢 | 分步查詢 | 延遲載入 | 集合屬性封裝)

  • 配置列名屬性名對映
  • resultMap也是用來定義結果集的封裝規則的(表的列名和pojo 的屬性名的對應關係);
  • resultMap標籤兩個屬性 type是pojo型別,id是唯一標識;表中的主鍵列用id 封裝,普通列用 result 封裝;
  • 用resultMap實現關聯查詢(前提pojo包裝pojo):
  1. 第一種方法是直接寫 property 的時候用屬性點屬性的方式就可以了;
  2. 第二種方法是在 resultMap 裡用 association 標籤實現關聯查詢,兩個屬性 property 和 javatype;
  • association 標籤用法
  • 可以用來實現關聯查詢;
  • 用 association 實現分步查詢:select屬性指定 mapper方法,column 屬性指定傳入方法的引數;
  • 關聯查詢時,如果想按需載入,就可以在全域性 settings 裡設定lazyloading 為true,實現get相應的pojo 的時候再發出sql向資料庫查詢;
  • collection 標籤用法
  • 用 collection 標籤實現集合型別屬性的封裝,屬性 property為相應的集合型別的屬性名,而ofType 是集合的泛型的型別;
  • collection 實現分步查詢和延遲載入:
  1. 實際上還是 select 將兩個介面方法、兩個sql關聯,再用 column 屬性傳入引數;
  2. 多個引數的傳遞可以用map,就是這樣的形式:{key1=col1,key2=col2};
  3. fetchType屬性可以設定延遲載入;
  • discriminator鑑別器根據列的值做出不同的處理:還是寫在 resultMap裡,內含case標籤指定各種值的處理方法(封裝方法),其中指定封裝資料的型別時,type 和 map 必須二選一;這個東西用的少;
<?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.wc.mapper.TuserMapper">
	<!-- <resultMap type="tuser" id="map1">
		<id property="uid" column="tid"/> 
		<result property="uname" column="uname"/>
		<result property="age" column="age"/>
		關聯查詢
		<association property="dept" javaType="department">
			<id property="did" column="did"/> 
			<result property="dname" column="dname"/>
		</association>
	</resultMap> -->
	
	<resultMap type="tuser" id="map2">
		<id property="uid" column="tid"/> 
		<result property="uname" column="uname"/>
		<result property="age" column="age"/>
		<result property="did" column="did"/>
		<!-- select step by step -->
		<association property="dept"
			select="com.wc.mapper.DepartmentMapper.getDeptById" column="did">
			<id property="did" column="did"/> 
			<result property="dname" column="dname"/>
		</association>
	</resultMap>
	<select id="getById" resultMap="map2">
		select * from tuser where tid = #{id}
	</select>
</mapper>

三、動態sql

1、if 判斷

(1)OGNL(物件圖導航語言)

  • 有點類似於 jsp 中的 el 表示式,可以用來取引數的值並作一些基本的運算;

(2)if 判斷

  • if 判斷拼接 where 條件存在的問題:就是可能會出現where後面直接是一個 and的情況
  1. 第一種方法:就是where 後面緊跟一個 1=1;
  2. 第二種方法:使用where 標籤,使用時注意條件的後就不要寫 and 了;
  3. 第三種方法:使用trim 標籤,可以通過屬性設定字首字尾和前後綴的覆蓋問題,where 前後多出的 and(or)都能解決;
  • set 標籤用來封裝修改條件,作用就是去除 set 的時候多餘的逗號,當然用 trim 標籤也可以實現,與if結合使用可以實現動態更新;

2、choose 分支選擇

(1)語法:choose----when----when----otherwise-----choose

(2)理解:類似於 java 中帶break 的 switch語句,只匹配一個條件;

3、foreach 遍歷

(1)遍歷集合拼接 where 條件(如:in 集合)

  • 幾個常用的屬性 collection、item、separator、open、close、index(map的時候就是map的key);

(2)實現資料的批量插入

  • mysql 第一種:在 values 後面用 foreach 遍歷拼接 sql;
  • mysql 第二種:直接整個插入語句來迴圈,需要在資料庫的 url 後面傳參開啟多條語句執行的支援;
  • oracle 第一種:用 plsql ,在begin 和 end 中來遍歷;
  • oracle 第二種:迴圈用 select 語句將集合中的值從偽表中查出,再用查出的結果進行插入;

4、其他

(1)內建引數:

  • 除了我們傳入的引數,還有內建的引數,這裡的內建引數可以取到也可以判斷
  • _parameter:封裝所有的引數,傳入的引數一個就是這個引數本身,傳入多個引數就是一個 map;
  • databaseId:全域性配置檔案裡面配置了 databaseproviderid這裡可以取到;
  • _parameter 和 if結合可以用來進行 where條件的拼接;
  • databaseId 和 if 結合使用可以用來在一個 select 元素裡寫兩個資料庫的 sql;

(2)bind 標籤:作用就是將傳入的引數賦值給一個變數方便以後的呼叫,連個屬性name 和 value;

(3)sql 片段:

  • 用 sql 標籤抽取可以重用的sql 片段方便以後在其他的sql 裡用include標籤用id引用,如查詢欄位的重用;
  • include 支援自定義 property ,在sql標籤的內部就能用${}取來使用;