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 的執行時行為。其引數詳情如下表所示:
設定引數 | 描述 | 有效值 | 預設值 |
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型別。
型別處理器 | 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語句。