1. 程式人生 > >MyBatis的體系結構和配置檔案詳解

MyBatis的體系結構和配置檔案詳解

一、SqlSessionFactory

MyBatis 的應用都是以一個 SqlSessionFactory 的例項為中心的,它是單個數據庫對映關係經過編譯後的記憶體映象;SqlSessionFactory 的例項可以通過 SqlSessionFactoryBuilder 獲得。而 SqlSessionFactoryBuilder 則可以從 XML 配置檔案或一個預先定製的 Configuration 的例項構建出 SqlSessionFactory 的例項,一般SqlSessionFactroy採用單例模式去建立。

SqlSessionFactory的一個重要作用就是建立SqlSession。

~SqlSession openSession() —— 建立SqlSession物件。

二、SqlSession

1.作用:SqlSession是執行持久化操作的物件,類似於JDBC的Connection。它是應用程式與持久儲存層之間執行互動操作的一個單執行緒物件,SqlSession底層封裝了JDBC連線,SqlSession 完全包含了面向資料庫執行 SQL 命令所需的所有方法,可以用它來直接執行已對映的Sql語句,並且每個執行緒有它自己獨立的SqlSession例項。SqlSession的例項不能共享,也是執行緒不安全的。使用完SqlSession之後應關閉session。

2.常用方法:

~int insert(String statement) —— 插入方法,引數statement是在配置檔案中定義的<insert>元素的id,返回執行sql語句所影響的行數。

~int insert(String statement,Object object) —— 插入方法,引數statement是在配置檔案中定義的<insert>元素的id,object是插入所需的引數,通常是物件或者Map,返回執行sql語句所影響的行數。

~int update(String statement) —— 更新方法,引數statement是在配置檔案中定義的<update> 元素的id,返回執行sql語句所影響的行數。

~ int update(String statement,Object object) —— 更新方法,引數statement是在配置檔案中定義的<update>元素的id,object是更新所需的引數,通常是物件或者Map,返回執行sql語句所影響的行數。

~ int delete(String statement) —— 刪除方法,引數statement是在配置檔案中定義的<delete>元素的id,返回執行sql語句所影響的行數。

~ int delete(String statement,Object object) —— 刪除方法,引數statement是在配置檔案中定義<delete>元素的id,object是刪除所需的引數,通常是物件或者Map,返回執行sql語句影響的行數。

~<T> T selectOne(String statement) —— 查詢方法,引數statement是在配置檔案中定義的<select>元素的id,返回執行sql語句查詢結果的泛型物件,通常查詢結果只有一條資料時才使用。

~ <T> T selectOne(String statement,Object object) —— 查詢方法,引數statement是在配置檔案中定義的<select>元素的id,object是查詢所需的引數,通常是物件或者Map,返回執行sql語句查詢結果的泛型物件,只在查詢結果只有一條資料時使用。

~ <E> List<E> selectList(String statement) —— 查詢方法,引數statement是在配置檔案中定義的<select>元素的id,返回sql語句查詢結果的泛型物件的集合。

~ <E> List<E> selectList(String statement,Object object) —— 查詢方法,引數statement是在配置檔案中定義的<select>元素的id,object是查詢所需的引數,通常是物件或者Map,返回執行sql語句查詢結果的泛型物件的集合。

~ <E> List<E> selectList(String statement,Object object,RowBounds rowBounds) —— 查詢方法,引數statement是在配置檔案中定義的<select>元素的id,object是查詢所需的引數,通常是物件或者Map,RowBounds物件用於分頁,它的兩個屬性:offset指查詢的當前頁數;limit指當前頁顯示多少條資料,返回執行sql語句查詢結果的泛型物件的集合。

~ <K,V> Map<K,V> selectMap(String statement,String mapKey) —— 查詢方法,引數statement是在配置檔案中定義的<select>元素的id,mapKey是返回資料的其中一個列名,執行sql語句查詢結果將會被封裝成一個Map集合返回,key就是引數mapKey傳入的列名,value是封裝的物件。

~ <K,V> Map<K,V> selectMap(String statement,Object object,String mapKey) —— 查詢方法,引數statement是在配置檔案中定義的<select>元素的id,object是查詢所需的引數,通常是物件或者Map,mapKey是返回資料的其中一個列名,執行sql語句查詢結果將會被封裝成一個Map集合返回,key就是引數mapKey傳入的列名,value是封裝的物件。

~ <K,V> Map<K,V> selectMap(String statement,Object object,String mapKey,RowBounds rowBounds) —— 查詢方法,引數statement是在配置檔案中定義的<select>元素的id,object是查詢所需的引數,通常是物件或者Map,RowBounds物件用於分頁,mapKey是返回資料的其中一個列名,執行sql語句查詢結果將會被封裝成一個Map集合返回,key就是引數mapKey傳入的列名,value是封裝的物件。

~void select(String statement,Object object,ResultHandler handler) —— 查詢方法,引數statement是在配置檔案中定義的<select>元素的id,object是查詢所需的引數,通常是物件或者Map,ResultHandler物件用來處理查詢返回的複雜結果集,通常用於多表查詢。

~ void select(String statement,Object object,RowBounds rowBounds,ResultHandler handler) —— 查詢方法,查詢方法,引數statement是在配置檔案中定義的<select>元素的id,object是查詢所需的引數,通常是物件或者Map,ResultHandler物件用來處理查詢返回的複雜結果集,RowBounds物件用於分頁。

~ void commit() —— 提交事務。

~ void rollback() —— 回滾事務。

~ void close() —— 關閉SqlSession物件。

~Connection getConnection() —— 獲得JDBC的資料庫連線物件。

~<T> T getMapper(Class<T> type) —— 返回mapper介面的代理物件,該物件關聯了SqlSession物件,開發者可以通過該物件直接呼叫方法操作資料庫,引數type是Mapper的介面型別。Mybatis官方手冊建議通過Mapper物件訪問MyBatis。

三、深入瞭解MyBatis的配置檔案

1.mybatis初始化過程:首先看一段程式碼

//讀取mybatis-config.xml檔案
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
//初始化mybatis,建立SqlSessionFactory類的例項
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//建立Session例項
SqlSession session = sqlSessionFactory.openSession();

其初始化經過的步驟:

(1)、呼叫SqlSessionFactoryBuilder物件的build(inputStream)方法。

(2)、SqlSessionFactoryBuilder會根據輸入流inputStream等資訊建立XMLConfigBuilder物件。

(3)、SqlSessionFactoryBuilder呼叫XMLConfigBuilder物件的parse()方法。

(4)、XMLConfigBuilder物件解析XML配置檔案返回Configuration物件。

(5)、SqlSessionFactoryBuilder根據Configuration物件建立一個DefaultSessionFactory物件。

(6)、SqlSessionFactoryBuilder返回DefaultSessionFactory物件給客戶端,供客戶端使用。

所以SqlSessionFactory是根據MyBatis的配置檔案mybatis-config.xml建立的。

2.Mybatis的配置檔案詳解

Mybatis包含以下配置元素包含:頂層configuration配置,properties 屬性,settings 設定,typeAliases 型別命名,typeHandlers 型別處理器,objectFactory 物件工廠,plugins 外掛,environments 環境 ,environment 環境變數,transactionManager 事務管理器,dataSource 資料來源,databaseIdProvider 資料庫廠商標識,mappers 對映器。

2.1 properties屬性

就是將java中屬性檔案配置,通過properties元素傳遞到mybatis配置資訊中:

例如:java專案中有一個配置檔案db.properties

driver = com.mysql.jdbc.Driver
url = jdbc:mysql://localhost:3306/mybatis
username = root
password = 123456

在mybatis-config.xml配置檔案中新增一個屬性

<properties resource="db.properties" />

那麼mybatis-config.xml配置的動態屬性的屬性值就可以進行相應的修改

<dataSource type="POOLED">
    <property name="driver" value="${driver}" />
    <property name="url" value="${url}" />
    <property name="username" value="${username}"/>
    <property name="password" value="${password}" />
</dataSource>

2.2 settings設定

settings會改變 MyBatis 的執行時行為。其引數詳情如下表所示:

settings設定的詳細說明
設定引數 描述 有效值 預設值
cacheEnabled 該配置影響所有對映器中配置的快取的全域性開關 true | false true
lazyLoadingEnabled 延遲載入的全域性開關。當開啟時,所有關聯物件都會延遲載入。特定關聯關係中可通過設定fetchType屬性來覆蓋該項的開關狀態 true | false false
aggressiveLazyLoading 當啟用時,對任意延遲屬性的呼叫會使帶有延遲載入屬性的物件完整載入;反之,每種屬性將會按需載入 true | false true
multipleResultSetsEnabled 是否允許單一語句返回多結果集(需要相容驅動) true | false true
useColumnLabel 使用列標籤代替列名。不同的驅動在這方面會有不同的表現。 true | false true
useGeneratedKeys 允許JDBC支援自動生成主鍵,需要驅動相容。如果設定為true則這個設定強制使用自動生成主鍵,儘管一些驅動不能相容但仍可正常工作。 true | false false
autoMappingBehavior 指定MyBaits應如果自動對映列到欄位或屬性。NONE表示取消自動對映;PARTIAL只會自動對映沒有定義巢狀結果集對映的結果集。FULL會自動對映任意複雜的結果集(無論是否巢狀) NONE | PARTIAL | FULL PARTIAL
autoMappingUnknownColumnBehavior

NONE:什麼都不做

WARNING:輸入警告

FAILING:對映失敗,丟擲SqlSessionException

NONE | WARNING | FAILING NONE
defaultExecutorType 配置預設的執行器。SIMPLE就是普通的執行器;REUSE執行器會重用預處理語句(prepared statements);BATCH執行器將重用語句並執行批量更新 SIMPLE | REUSE | BATCH SIMPLE
defaultStatementTimeout 設定超時時間,它決定驅動等待資料庫響應的秒數 integer 沒有設定
defaultFetchSize 預設返回的結果集的大小 integer 沒有設定
safeRowBoundsEnabled 允許在巢狀語句中使用分頁(RowBounds) true | false  false
mapUnderscoreToCamelCase 是否開啟自動駝峰命名規則(camelcase)對映 true | false false
localCacheScope MyBatis利用本地快取機制(LocalCache)防止迴圈引用(circular references)和加速重複巢狀查詢。預設值為session,這種情況下會快取一個會話中執行的所有查詢。若設定值為STATEMENT,則本地會話僅用在語句執行上,對相同SqlSession的不同調用將不會共享資料 SESSION | STATEMENT SESSION
jdbcTypeForNull 當沒有為引數提供特定的JDBC型別時,為空值指定JDBC型別。某些驅動需要指定列的JDBC型別,多數情況直接用一般型別即可,比如NULL、VARCHAR或OTHER NULL | VARCHAR | OTHER OTHER
lazyLoadTriggerMethods 指定哪個物件的方法觸發一次延遲載入 方法名的list集合 equals,clone,hashCode,toString
defaultScriptingLanguage 指定動態SQL生成的預設語言 一個類型別名或完全限定類名

org.apache.ibatis.scripting.xmltags.XMLDynamicLanguageDriver

callSettersOnNulls 指定當結果集中值為null時是否呼叫對映物件的setter(map物件時為put)方法,這對於有Map.keySet()依賴或null值初始化時是有用的。注意基本型別(int、boolean等)是不能設定成null的 true | false false
logPrefix 指定MyBatis增加到日誌名稱的字首 String 沒有設定
logImpl 指定MyBatis所有日誌的具體實現,未指定時將自動查詢

SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMON | S_LOGGING | STDOUT_LOGGING

| NO_LOGGING 

沒有設定
proxyFactory 指定Mybatis建立具有延遲載入能力的物件所用到的代理工具 CGLIB | JAVASSIST JAVASSIST (MyBatis 3.3 or above)

一個完整的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="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>

2.3 typeAliases型別命名

可為java型別設定的一個短的名字。該元素可減少類完全限定名的冗餘。

<typeAliases>
    <typeAlias type="com.hu.model.User" alias="user"/>
</typeAliases>

在其他配置使用com.hu.model.User可用user代替

 <insert id="saveUser" parameterType="user" useGeneratedKeys="true">
     insert into TB_USER(name,sex,age) values (#{name},#{sex},#{age})
 </insert>

也可以指定一個包名,MyBatis會在包名下面搜尋需要的JavaBean

<typeAliases>
    <package name="com.hu.model"/>
</typeAliases>

在每一個包com.hu.model中的javaBean,在沒有註解的情況下,會使用Bean的首字母小寫的非限定類名來作為它的別名。若有註解,則使用其註解的值。

2.4 typeHandlers 型別處理器

mybatis在預處理語句設定一個引數或從結果集中取出一個值時,都會用型別處理器將獲取的值以合適的方式轉換成Java型別。

MyBatis預設的型別處理器
型別處理器 java型別 JDBC型別
BooleanTypeHandler java.lang.Boolean,boolean 資料庫相容的Boolean
ByteTypeHandler java.lang.Byte, byte 資料庫相容的NUMERIC 或 BYTE
ShortTypeHandler

java.lang.Short,short

資料庫相容的NUMERIC 或SHORT INTEGER
IntegerTypeHandler java.lang.Integer,int 資料庫相容的NUMERIC 或 INTEGER
LongTypeHandler java.lang.Long,long 資料庫相容的NUMERIC 或 LONG INTEGER
FloatTypeHandler java.lang.Float,float 資料庫相容的NUMERIC 或 FLOAT
DoubleTypeHandler java.lang.Double,double 資料庫相容的NUMERIC 或 DOUBLE
BigDecimalTypeHandler java.math.BigDecimal 資料庫相容的NUMERIC 或 DECIMAL
StringTypeHandler java.lang.String CHAR,VARCHAR
ClobReaderTypeHandler java.io.Reader
ClobTypeHandler java.lang.String CLOB,LONGVARCHAR
NStringTypeHandler java.lang.String NVARCHAR、NCHAR
BlobInputStreamTypeHandler java.io.InputStream
ByteArrayTypeHandler byte[] 資料庫相容的位元組流型別
BlobTypeHandler byte[] BLOB、LONGVARBINARY
DateTypeHandler java.util.Date TIMESTAMP
DateOnlyTypeHandler java.util.Date DATE
TimeOnlyTypeHandler java.util.Date TIME
SqlTimestampTypeHandler java.sql.Timestamp TIMESTAMP
SqlDateTypeHandler java.sql.Date DATE
SqlTimeTypeHandler java.sql.Time TIME
ObjectTypeHandler Any OTHER 或 未指定型別
EnumTypeHandler Enumeration Type VARCHAR,任何相容的字串型別,儲存列舉的名稱(而不是索引)
EnumOrdinalTypeHandler Enumeration Type 任何相容的NUMERIC 或 DOUBLE型別,儲存列舉的名稱(而不是索引)

2.5 environments配置環境

environments就是配置mybatis的執行環境,包括事務(transactionManager)和資料來源(dataSource)。MyBatis可以配置多種環境,但是每個SqlSessionFactory例項只能選擇一個環境,即每個資料庫對應一個SqlSessionFactory例項,如果想要連線兩個資料庫,則需要建立兩個SqlSessionFactory例項,以此類推。

environments環境配置例項:

 <!--環境配置,即連線的資料庫-->
    <environments default="mysql">
        <environment id="mysql">
            <!--指定事務管理型別,type="JDBC"指直接使用JDBC的提交和回滾設定-->
            <transactionManager type="JDBC" />
            <!-- dataSource資料來源配置,POOLED是JDBC連線物件的資料來源連線池的實現。-->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver" />
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis" />
                <property name="username" value="root"/>
                <property name="password" value="123456" />
            </dataSource>
        </environment>
    </environments>

各種屬性說明:

預設的環境id(例:default="mysql")

每個environment 元素定義的環境id(例:id="mysql")

事務管理器的配置(例:type="JDBC")

資料來源的配置(例:type="POOLED")

environment的id可以隨意命名,但environments的id必須匹配其中一個environment的id

<transactionManager>表示事務管理器配置,在MyBatis中有JDBC和MANAGED兩種型別的事務管理器:

        JDBC:這個配置就是直接使用了JDBC的提交和回滾設定,它依賴於從資料來源得到的連線來管理事務範圍。

        MANAGED:這個配置幾乎沒做什麼。它從來不提交或回滾一個連線,而是讓容器來管理事務的整個生命週期。預設情況下它會關閉連線,然而一些容器並不希望這樣,可以將closeConnection屬性設定為false來阻止它預設的關閉行為。

transactionManager的MANAGED配置例項:

<transactionManager type="MANAGED">
    <property name="closeConnection" value="false" />
</transactionManager>

注:如果使用的是Spring+MyBatis的架構,則沒有必要配置MyBatis的事務管理器,因為會使用Spring框架的自帶管理器來覆蓋掉MyBatis的配置。

<dataSoucre>表示資料來源配置,在MyBatis中有UNPOOLED、POOLED、JNDI三種資料來源型別:

        (1)UNPOOLED:這個資料來源的實現只是每次被請求時開啟和關閉連線。對程式沒有效能要求時可使用此配置。

        UNPOOLED包含5種屬性配置:

        ·driver —— 這是JDBC驅動的java類的完全限定名。

        ·url —— 這是資料庫的JDBC URL 地址。

        ·username —— 登入資料庫的使用者名稱。

        ·password —— 登入資料庫的密碼。

        ·defaultTransactionIsolationLevel —— 預設的連線事務隔離級別。

        (2)POOLED:這種資料來源的實現利用了“池”的概念將JDBC連線物件組織起來,避免了建立新的連線例項時所必須的初始化和認證時間。其配置包含上述5種屬性外,還有如下屬性可配置:

        ·poolMaximumActiveConnections —— 在任意時間可以存在的活動(正在使用)連線數量,預設值為10。

        ·poolMaximumldleConnections —— 任意時間可能存在的空閒連線數。

        ·poolMaximumCheckoutTime —— 在被強制返回之前,池中連線被檢出時間,預設值為20000毫米(20s)。

        ·poolTimeToWait —— 這是一個底層設定,如果獲取連線花費相當長的時間,它會給連線池列印狀態日誌並重新嘗試獲取一個連線(避免在誤配置的情況下一直安靜地失敗),預設值為20000毫秒(20s)。

       ·poolPingQuery —— 傳送到資料庫的偵測查詢,用來檢查連線是否處在正常工作秩序中並準備接受請求。預設是“NO PING QUERY SET”,這會導致多數資料庫驅動失敗時帶有一個恰當的錯誤訊息。

        ·poolPingEnabled —— 是否啟用偵測查詢。如開啟,必須使用一個可執行的sql語句設定poolPingQuery屬性(最好是一個非常快的sql),預設值為false。

        ·poolPingConnectionsNotUsedFor —— 配置poolPingQuery的使用頻度。這可以被設定成匹配具體的資料庫連線超時時間,來避免不必要的偵測,預設值為0(即所有連線每一時刻都被偵測,僅當poolPingEnabled為true時適用)。

        (3)JNDI:這種資料來源的實現是為了能在EJB或應用伺服器這類容器中使用,容器可以集中或在外部配置資料來源,然後放置一個JNDI上下文的引用。這中資料來源的只有兩種配置:

        ·initial_context —— 用來在InitialContext中國尋找上下文(即initialContext.lookup(initial_context))。這是個可選屬性,如果忽略,那麼data_source屬性將會直接從InitialContext中尋找。

        ·data_source —— 這是引用資料來源例項位置的上下文路徑。若提供了initial_context配置則會在其返回的上下文中進行查詢,沒有提供則直接在InitialContext中查詢。

JNDI的配置例項如下:

<dataSource type="JNDI">
    <property name="initial_context" value="java:/comp/env"/>
    <property name="data_source" value="fkjavads"/>
</dataSource>

2.6 mapper 對映器

MyBatis需要自定義sql語句,而mapper則是告訴Mybatis到哪裡去找哪些自定義的sql語句的檔案,可以使用相對於類路徑的資源引用或完全限定資源定位符(包括file:///的URL),以及類名和包名等。

   <!-- mappers告訴了MyBatis去哪裡找持久化類的對映檔案-->
    <mappers>
      
        <mapper resource="com.hu.mapper.UserMapper.xml"/>
        <!--使用本地檔案-->
        <mapper url="file:///D:/UserMapper.xml"/>
        <!--使用介面類-->
        <mapper class="com.hu.mapper.UserMapper" />
        <!--使用包名-->
        <package name="com.hu.mapper"/>
    </mappers>

三、Mapper XML對映檔案詳解

Mybatis的真正強大之處在於它的對映語句,使用對映器的xml檔案進行編寫sql語句,相較於使用JDBC來說,可以省略多數程式碼,使程式碼更加簡潔。

對映檔案常用元素如下:

·select —— 對映查詢語句。

·insert —— 對映插入語句。

·update —— 對映更新語句。

·delete —— 對映刪除語句。

·sql —— 可被其他語句引用的可重用語句塊。

·cache —— 給定名稱空間的快取配置。

·cache-ref —— 其他名稱空間快取配置的引用。

·resultMap —— 最複雜最強大的元素,用來描述如何從資料庫結果集中載入物件。

3.1 select

select元素用來對映查詢語句。例項如下:

<select id="selectUser" parameterType="Integer" resultType="com.hu.model.User">
    select * from TB_USER where id = #{id}
</select>

其中select元素有許多可配置的屬性,如下:

<select id="selectUser" parameterType="Integer"
        resultType="hashMap" resultMap="userResultMap"
        flushCache="true" useCache="true"
        timeout="10000" fetchSize="128"
        statementType="PREPARED" resultSetType="FORWARD_ONLY">
</select>

其中各元素的描述如下:

·id —— 在名稱空間中唯一的識別符號,可以被用來引用這條語句。

·parameterType —— 傳入這條語句的引數類的完全限定名或別名。這個屬性是可選的,Mybatis可以通過TypeHandler推斷出具體傳入語句的引數,預設值為unset。

·resultType —— sql語句返回的期望型別的類的完全限定名或別名。如果語句返回的是集合,則是這個集合裡包含的型別。返回時只能使用resultType或resutlMap其中的一種,兩個不能同時存在。

·resultMap —— 外部resultMap的命名引用,可理解為可自己定義返回的類中的各個欄位,一般用於複雜的對映情況。

·flushCache —— 如果設定為true,則只要語句被呼叫,就會導致本地快取和二級快取都被清空,預設值為false。

·useCache —— 如果設定為true,則這要本語句的結果被二級快取,在select元素當中預設值為true。

·timeout —— 這個設定在丟擲異常之前,驅動程式等待資料庫返回請求結果的秒數。預設值為unset(依賴驅動)。

·fetchSize —— 嘗試影響驅動程式每次批量返回的結果行數和這個設定值相等。預設值為unset(依賴驅動)。

·statementType —— 值為STATEMENT、PREPARED、CALLABLE。這會讓MyBatis分別使用jdbc中的statement、PreparedStatement、CallableStatement,預設值為PREPARED。

·resultSetType —— 結果集的型別,可選值為FORWARD_ONLY、SCROLL_SENSITIVE、SCROLL_INSENSITIVE,預設值為unset(依賴驅動)。

·resultOrdered —— 這個屬性僅針對巢狀結果select語句適用:如果為true,就是假設包含了巢狀結果集或是分組了,當返回一個主結果行的時候,就不會發生對前面結果集引用的情況。這樣做的好處就是在獲取巢狀的結果集時不至於導致記憶體不夠用。預設值為 false。

·resultSets —— 這個屬性僅對多結果集的情況適用,它將列出語句執行後返回的結果集並給每個結果集一個名稱,名稱是逗號分隔的。

3.2 insert、update和delete

其中各元素有許多可配置的屬性,如下:

<insert id="insertUser" parameterType="com.hu.model.User"
        flushCache="true" statementType="PREPARED"
        keyProperty="" keyColumn=""
        useGeneratedKeys="" timeout="20">
</insert>
  
      
<update id="updateUser" parameterType="com.hu.model.User"
        flushCache="true" statementType="PREPARED"
        timeout="20">
</update>

<delete id="deleteUser" parameterType="com.hu.model.User"
        flushCache="true" statementType="PREPARED"
        timeout="20">            
</delete>

其中各元素屬性大多數和select一致,特有屬性描述如下:

·useGeneratedKeys —— (僅對insert和update有用)這會讓MyBatis使用JDBC的getGeneratedKeys方法來獲取由資料庫內部生成的主鍵,預設值為false。

·keyProperty —— (僅對insert和update有用)唯一標示屬性,MyBatis會通過getGeneratedKeys的返回值或者通過insert語句的selectKey子元素設定它的鍵值,預設為unset。如果希望得到多個生成的列,也可以是逗號分隔的屬性名稱列表。

·keyColumn —— (僅對insert和update有用)通過生成的鍵值設定表中的列名,這個設定僅對某些資料庫(像PostgreSQL)是必須的,當主鍵列不是表中的第一列時需要設定。如果希望得到多個生成的列,也可以示逗號分隔的屬性名稱列表。

對於insert語句來說,在插入資料成功後需要返回其表中的主鍵值,根據資料庫的主鍵生成策略不同,配置也有多種;如果資料庫支援自動生成主鍵的欄位(如Mysql和SQL Server),那麼可以設定useGeneratedKeys=“true”,然後再把keyProperty設定到目標屬性上就可以了。語句例項如下:

<insert id="insertUser" useGeneratedKeys="true" keyProperty="id">
    insert into TB_USER (username,password,address) values 
    (#{username},#{password},#{address})
</insert>

對於不支援自動生成主鍵的資料庫(如Oracle)或可能不支援自動生成主鍵的jdbc驅動來說,Mybatis有另外一種方法生成主鍵。

<insert id="insertUser">
    <selectKey keyProperty="id" resultType="Integer" order="BEFORE">
        select SQQUENCE_TB_USER.nextval as id from dual
    </selectKey>
    insert into TB_USER (id,username,password,address)
    values (#{id},#{username},#{password},#{address})
</insert>

上述程式碼selectKey元素將會首先執行,查詢到SEQUENCE序列,TB_USER的id會被設定,然後在執行insert語句;其中selectKey元素描述如下:

<selectKey keyProperty="id" 
           resultType="Integer" 
           order="BEFORE" 
           statementType="PREPARED">
            

屬性詳細解析:

·keyProperty —— selectKey語句結果被設定的目標屬性(一般會設定到id屬性上)。如果希望得到多個生成的列,也可以是逗號分隔的屬性名稱列表。

·keyColumn —— 匹配屬性的返回結果集中的列名稱。如果希望得到多個生成的列,也可以是逗號分隔的屬性名稱列表。

·resultType —— 結果的型別Mybatis允許任何簡單型別用作主鍵的型別,包括字串,如果希望作用於多個生成的列,則可以使用一個包含期望屬性的Object或一個Map。

·order —— 可設定為BEFORE或AFTER,如果設定為BEFORE,就是首先生成主鍵,然後將keyProperty的值插入到語句中;如果設定為AFTER,那就先執行插入語句,然後在執行selectKey元素。

·statementType —— 值為STATEMENT、PREPARED、CALLABLE。這會讓MyBatis分別使用jdbc中的statement、PreparedStatement、CallableStatement,預設值為PREPARED。

3.3 sql

sql元素可以被用來定義可重用的sql程式碼,可以包含在其他語句中。它可以被靜態地(在載入引數時)引數化。程式碼例項:

<sql id="userColumns"> id,username,password</sql>

在別語句中就可呼叫這個sql程式碼,例項如下:

<select id="selectUsers" resultType="map">
    select 
        <include refid="userColumns"></include>
    from TB_USER 
</select>

3.4 引數(Parameters)

parameterType傳入sql語句的引數型別,引數型別可以是原生的型別或簡單資料型別,也可傳入一個物件,例如:

<insert id="insertUser" parameterType="User">
    insert into user (id,username,password)
     values (#{id},#{username},#{password})
</insert>

如果是Userr實體被傳入sql語句中,#{id}則會查詢物件User的id屬性。

3.5 ResultMap(ResultType)

resultMap(ResultType)的作用是告訴MyBatis將從結果集中取出的資料轉換成開發著所需要的物件。例如:

<select id="selectUser" resultType="map">
    select * from tb_user
</select>

上訴語句就是查詢tb_user表中的所有資料。resultTyep=“map”表示返回的資料是一個Map集合(表的列名作為key,列值作為value)。雖然資料被封裝成了Map集合,但是Map集合並不能很好的描述一個領域模型。所以最好還是使用javaBeans或pojo來作為領域模型描述資料。

如果查詢的結果是由兩張表關聯的欄位組成,則就不能用resultType,這時就可以使用resultMap,或者資料庫表的欄位和例項不對應,這時也可以使用resutlMap。例如:

建立一個數據庫表:

create table user2(
    user_id int primary key auto_increment,
    user_name archer(8),
    user_sex archer(8),
    user_age int(4)
);

java對應的實體:

public class User {

   /** 標識 */
    private Integer id;

    /** 姓名 */
    private String name;

    /** 性別 */
    private String sex;

    /** 年齡 */
    private Integer age;

    //省略get/set方法
}

這個時候就可以使用resultMap:

<resultMap id="userResultMap" type="com.hu.model.User">
    <id property="id" column="user_id" />
    <result property="name" column="user_name"/>
    <result property="sex" column="user_sex" />
    <result property="age" column="user_age" />
</resultMap>

<select id="selectUser2" resultMap="userResultMap">
    select * from user2
 </select>

上述resultMap元素屬性解析如下:

·id —— resultMap的唯一識別符號。

·type —— resultMap實際返回的型別。

resultMap的兩個子元素:

·id —— 表示資料庫表的主鍵,其中,column屬性表示資料庫表的列名,property表示資料庫列對映到返回型別的屬性。

·result —— 表示資料庫表普通列,其中,column屬性表示資料庫表的列名,property表示資料庫列對映到返回型別的屬性。

對於多表的關聯對映也需要使用ResultMap來實現,例如:先建立兩個關聯的表

create table class{
    id int primary key auto_increment,
    code varchar(8)
};


create table student{
    id int primary key auto_increment,
    name varchar(8),
    sex char(3),
    age int(5),
    clazz_id int,
    foreign key (class_id) references class(id)

};

在java分別對應的實體為:

public class Clazz {

    private Integer id;

    private String code;

    //省略get/set方法
}


public class Student {

    private Integer id;

    private String name;

    private String sex;

    private String age;

    private Clazz clazz;

   //省略get/set方法

}

mapper對映檔案的寫法為:

 <resultMap id="studentClazz" type="com.hu.model.Student">
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <result property="sex" column="sex"/>
        <result property="age" column="age"/>
        <!--關聯對映-->
        <association property="clazz" column="clazz_id" javaType="com.hu.model.Clazz" select="selectClazzId"/>
    </resultMap>
    
    <!--根據班級id查詢班級-->
    <select id="selectClazzId" resultType="com.hu.model.Clazz">
        select * from  clazz where  id = #{id}
    </select>
    <!--查詢所有學生資訊-->
    <select id="selectStudent" resultMap="studentClazz">
        select * from student
    </select>

上訴<association>元素解釋如下:

·column —— 表示資料庫表的列名。

·property —— 表示返回型別student的屬性名clazz

·javaType —— 表示該屬性對應的型別名稱。

·select —— 表示執行一條查詢語句,將查詢到的資料封裝property所代表的型別物件當中。上面的selectClazzId就是一條sql語句。

如果想查詢一個班級所有的學生資訊的話,首先在clazz.java類中增加一個students欄位,其型別為List集合。此時對映檔案如下所示:

<resultMap id="clazzStudent" type="com.hu.model.Clazz">
        <id property="id" column="id" />
        <result property="code" column="code" />
        <!--班級的學生屬性,因為一個班級有多個學生,所以該屬性是一個集合-->
        <collection property="students" javaType="ArrayList" column="id" ofType="com.hu.model.Student"
                    select="selectStudentId" />
        
    </resultMap>
    <!--根據班級id查詢學生-->
    <select id="selectStudentId" resultType="com.hu.model.Student">
        select * from student where clazz_id = #{id}
    </select>
    <!--查詢所有班級資訊-->
    <select id="selectClazz" resultMap="clazzStudent">
        select * from clazz
    </select>

其中元素<collection>詳解如下:

·property —— 表示返回型別Clazz的屬性名students。

·javaType —— 表示該屬性對應的型別名稱。

·ofType —— 表示集合當中的型別。

·column —— 表示使用id作為引數進行之後的select語句查詢。

·select —— 表示執行一條查詢語句,將查詢到的資料封裝property所代表的型別物件當中。上面的selectStudentId就是一條sql語句。