MyBatis實戰之配置
MyBatis最重要的配置也就兩個,一個是mybatis-config.xml,又稱MyBatis的全域性配置,另一個就是XXXDao.xml或XXXMapper.xml對映配置。
今天主要講的兩個配置就是這兩個。
一、mybatis-config.xml配置詳解
<?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> <typeAliases> <package name="com.blog.entity"/> </typeAliases> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <propertyname="driver" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://127.0.0.1:3306/blog_test"/> <property name="username" value="root"/> <property name="password" value="1234"/> </dataSource> </environment> </environments><mappers> <mapper resource="mybatis/mapping/UserDao.xml"/> </mappers> </configuration>
1.properties元素
properties是一個配置屬性的元素,讓我們能在配置檔案的上下文使用它。
MyBatis提供3種配置方式。
(1)properties子元素(如上述);
(2)properties配置檔案(例如讀取jdbc.properties配置檔案,這個在spring-mybatis整合得以體現);
(3)程式引數傳遞(本質上是讀取properties配置檔案,通過鍵值對的讀取並傳遞引數);
關於它們的優先順序
首先,properties元素體內指定的屬性首先被讀取;
其次,根據properties元素中的resource屬性讀取類路徑下屬性檔案,或者根據url屬性指定的路徑讀取屬性檔案,並覆蓋已讀取的同名屬性;
最後,讀取作為方法引數傳遞的屬性,並覆蓋已讀取的同名屬性;
因此,通過方法引數傳遞的屬性具有最高優先順序,resource/url屬性中指定的配置檔案次之,最低優先順序的是properties屬性中指定的屬性。因此,實際操作中我們需要注意以下三點:
(1)不要使用混合的方式,這樣會使得管理混亂;
(2)首先方式是使用properties檔案;
(3)如果我們需要對其進行加密或者其他加工以滿足特殊的要求,不妨按照程式引數傳遞方式;
2.設定
設定(settings)在MyBatis中是最複雜的配置,同時也是最為重要的配置內容之一,它會改變MyBatis執行時的行為。即使不配置settings,MyBatis也可以正常的工作,不過了解settings的配置內容,以及它們的作用仍然十分必要。
Settings的配置內容如下圖所示:
圖一:
圖二:
圖三:
圖四:
圖五:
圖六:
配置一般情況下不需要修改太多,只僅僅修改少量就行。
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="defaultExecutorType" value="SIMPLE" /> <setting name="defaultStatementTimeout" value="25000" /> <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" />
3.別名
MyBatis系統定義了一些經常使用的型別的別名,例如,數值、字串、日期和集合等,我們可以在MyBatis中直接使用它們,在使用時不要重複定義把它們給覆蓋了。
讓我們看看MyBatis已經定義好的別名(支援陣列型別的只要加"[]" 即可使用,比如Date數組別名可以用date[]代替)。
系統定義的typeAliases 如圖所示:
圖一:
圖二:
圖三:
我們在MyBatis實戰之初步 說到過別名和它的三種配置方式,所以此處不再贅述。
4.typeHandler型別處理器
MyBatis在預處理語句(PreparedStatement)中設定一個引數時,或者從結果集(ResultSet)中取出一個值,都會用註冊了的typeHandler進行處理。
由於資料庫可能來自不同廠商,不同的廠商設定的引數可能存在差異,同時資料庫也可以自定義資料型別,typeHandler允許根據專案的需要自定義設定Java傳遞到資料庫的引數中,或者從資料庫讀出資料,我們也需要進行特殊的處理,這些都可以在定義的typeHandler中處理,尤其在使用列舉的時候我們常常需要使用typeHandler進行轉換。
typeHandler和別名一樣,分為MyBatis系統定義和使用者自定義兩種。一般來說,使用MyBatis系統定義就可以實現大部分的功能,如果使用使用者自定義的typeHandler,我們在處理的時候務必小心謹慎,以避免出現不必要的錯誤。
typeHandler 常用的配置為Java型別(javaType)、JDBC型別(jdbcType)。typeHandler的作用就是將引數從javaType轉化為jdbcType,或者從資料庫取出結果時把jdbcType轉化為javaType。
系統註冊的typeHandle簡介,如下圖所示:
圖一:
圖二:
需要注意以下幾點?
(1)數值型別的精度,資料庫Int、double、decimal這些型別和Java的精度、長度都是不一樣的;
(2)時間精度,取資料到日用DateOnlyTypeHandler即可,用到精度為秒的用SqlTimestamp、TypeHandler等;
讓我們選取一個MyBatis系統自定義的typeHandler,並瞭解它的具體內容。我們可以看到MyBatis原始碼包org.apache.ibatis.type下面定義的StringTypeHandler。StringTypeHandler是一個常用的typeHandler,負責處理String型別。
StringTypeHandler原始碼如下:
* Copyright 2009-2015 the original author or authors. package org.apache.ibatis.type; import java.sql.CallableStatement; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; /** * @author Clinton Begin */ public class StringTypeHandler extends BaseTypeHandler<String> { @Override public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException { ps.setString(i, parameter); } @Override public String getNullableResult(ResultSet rs, String columnName) throws SQLException { return rs.getString(columnName); } @Override public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException { return rs.getString(columnIndex); } @Override public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { return cs.getString(columnIndex); } }
說明一下上面的程式碼:
StringTypeHandler繼承BaseTypeHandler,而BaseTypeHandler實現介面typeHandler,並且自己定義了4個抽象的方法。所以繼承它的時候,正如本例一樣,正如本例一樣需要實現其定義的4個抽象方法,這些方法已經在StringTypeHandler中用@Override註解註明了。
setParameter是PreparedStatement物件設定引數,它允許我們自己填寫變換規則。
getResult則分為ResultSet用列名(columnName)或者使用列下標(columnIndex)來獲取結果資料。其中還包括了用CallableStatement(儲存過程)獲取結果及資料的方法。
如果你想自定義Handler,除了編寫一個Java類之外,還需要在mybatis-config.xml配置如下內容:
<typeHandlers> <typeHandler handler="com.blog.typehandler.MyStringHandler" javaType="string" jdbcType="varchar"/> </typeHandlers>
5.ObjectFactory
當MyBatis在構建一個結果返回的時候,都會使用ObjectFactory(物件工廠)去構建POJO,在MyBatis中可以定製自己的物件工廠。一般來說我們使用預設的ObjectFactory即可,MyBatis中預設的ObjectFactory是由org.apache.ibatis.reflection.factory.DefaultObjectFactory來提供的。在大部分的場景下我們都不用修改,如果要定製特定的工廠則需要進行配置。
例如我們自定義個ObjectFactory就需要在mybatis-config.xml配置如下內容:
<objectFactory type="com.blog.custom.MyObjectFactory"> <property name="userName" value="MyObjectFacotry"/> </objectFactory>
6.外掛
外掛是比較複雜的,使用時要特別小心。使用外掛將覆蓋一些MyBatis內部核心物件的行為,在沒有了解MyBatiss內部執行原理之前我們沒有必要去討論它,後面會說的。
7.environment配置環境
配置環境可以註冊多個數據源,每個資料來源分為兩大部分,一個是資料庫源的配置,另一個是資料庫事務的配置。
資料來源配置如下:
<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://127.0.0.1:3306/blog_test"/> <property name="username" value="root"/> <property name="password" value="1234"/> </dataSource> </environment> </environments>
分析下上述配置:
(1)environments中的屬性default,標明在預設的情況下,我們將啟動哪個資料來源配置;
(2)environment元素是配置一個數據源的開始,屬性id是設定這個資料來源的標誌,以便MyBatis上下文使用它;
(3)transactionManager配置的資料庫事務,其中type屬性有三種配置方式:
a.JDBC,採用JDBC方式管理事務,在獨立編碼中我們常常使用;
b.MANAGED,採用容器方式管理事務,在JNDI資料來源中常用;
c.自定義,由使用者自定義資料庫事務管理辦法,適用於特殊應用。
(4)property元素則是可以配置資料來源的各類屬性,假如在此配置autoCommit=false,則是要求資料來源不自動提交,預設情況是自動提交;
(5)dataSource標籤,是配置資料來源連線的資訊,type屬性是提供我們對資料庫連線方式的配置,同樣MyBatis提供了這麼幾種配置方式:
a.UNPOOLED,非連線池資料庫;
b.POOLED,連線池資料庫;
c.JNDI,JNDI資料來源;
d.自定義資料來源;
其中,配置的property元素,就是定義資料庫的各類引數。
關於資料庫事務MyBatis,它是由SqlSession去控制的,我們通過SqlSession提交或者回滾。我們插入一個角色物件,如果成功就提交,否則就回滾。不過大部分情況都是由Spring框架去控制。後面會講到。
MyBatis內部為我們提供三種資料來源的實現方式:
(1)UNPOOLED,非連線池,使用MyBatis提供的org.apache.ibatis.datasource.unpooled.UnpooledDataSource實現;
(2)POOLED,連線池,使用MyBatis提供的org.apache.ibatis.datasource.pooled.PooledDataSource實現;
(3)JNDI,使用MyBatis提供的org.apache.ibatis.datasource.jndi.JndiDataSourceFactory來獲取資料來源;
我們只需把資料來源的屬性type定義為UNPOOLED、POOLED、JNDI即可。
9.databaseIdProvider 資料庫廠商標識
在相同資料庫廠商的環境下,資料庫廠商標識沒有什麼意義,在實際的應用中使用得比較少,因為使用不同廠商資料庫的系統還是比較少的。MyBatis可能會執行在不同廠商的資料庫中,它為此提供一個數據庫標識,並提供自定義,它的作用在於指定SQL到對應的資料庫廠商提供的資料庫中執行。
這個不是特別重要,在此不詳說,告訴讀者有個這玩意。