1.SQL映射配置文件的結構概覽
- cache – 配置給定命名空間的緩存。
- cache-ref – 從其他命名空間引用緩存配置。
- resultMap – 最復雜,也是最有力量的元素,用來描述如何從數據庫結果集中來加載你的對象。
parameterMap– 已經被廢棄了!老式風格的參數映射。內聯參數是首選,這個元 素可能在將來被移除。這里不會記錄。- sql – 可以重用的 SQL 塊,也可以被其他語句引用。
- insert – 映射插入語句
- update – 映射更新語句
- delete – 映射刪除語句
- select – 映射查詢語句
2.select元素
簡單示例:
<select id=”selectPerson” parameterType=”int” resultType=”hashmap”> SELECT * FROM PERSON WHERE ID = #{id} </select>
這段sql語句的意思是傳入一個int類型的參數給select語句,返回的結果集保存在hashmap中,hashmap的key為字段名。
這里的#{id}就是使用PrepareStatement的方式傳入參數,即像這樣:
String selectPerson = “SELECT * FROM PERSON WHERE ID=?”; PreparedStatement ps = conn.prepareStatement(selectPerson); ps.setInt(1,id);
select元素支持的屬性:
屬性 | 描述 |
---|---|
id | 在命名空間中唯一的標識符,可以被用來引用這條語句。 |
parameterType | 將會傳入這條語句的參數類的完全限定名或別名。 |
resultType | 從這條語句中返回的期望類型的類的完全限定名或別名。注意集 合情形,那應該是集合可以包含的類型,而不能是集合本身。使 用 resultType 或 resultMap,但不能同時使用。 |
resultMap | 命名引用外部的 resultMap。 返回 map 是 MyBatis 最具力量的特性, 對其有一個很好的理解的話, 許多復雜映射的情形就能被解決了。 使用 resultMap 或 resultType,但不能同時使用。 |
flushCache | 將其設置為 true,不論語句什么時候被帶哦用,都會導致緩存被 清空。默認值:false。 |
useCache | 將其設置為 true, 將會導致本條語句的結果被緩存。 默認值: true。 |
timeout | 這個設置驅動程序等待數據庫返回請求結果,並拋出異常時間的 最大等待值。默認不設置(驅動自行處理) |
fetchSize | 這是暗示驅動程序每次批量返回的結果行數。默認不設置(驅動 自行處理)。 |
statementType | STA TEMENT,PREPARED 或 CALLABLE 的一種。 這會讓 MyBatis 使用選擇使用 Statement,PreparedStatement 或 CallableStatement。 默認值:PREPARED。 |
resultSetType | FORWARD_ONLY|SCROLL_SENSITIVE|SCROLL_INSENSITIVE 中的一種。默認是不設置(驅動自行處理)。 |
databaseId | In case there is a configured databaseIdProvider, MyBatis will load all statements with no databaseId attribute or with a databaseId that matches the current one. If case the same statement if found with and without the databaseId the latter will be discarded. |
3.Insert、update、delete 元素
數據修改語句insert、update 和delete 的配置使用都非常相似,只是insert元素多了兩個屬性配置(useGeneratedKey,keyProperty,keyColumn)。
下面是insert元素的示例(update,delete元素也差不多):
<!--自動生成主鍵--> <insert id="insertAuthor" parameterType="domain.blog.Author" useGeneratedKeys=”true” keyProperty=”id”> insert into Author (username,password,email,bio) values (#{username},#{password},#{email},#{bio}) </insert>
<!--通過一個查詢來生成主鍵--> <insert id="insertAuthor" parameterType="domain.blog.Author"> <selectKey keyProperty="id" resultType="int" order="BEFORE"> select CAST(RANDOM()*1000000 as INTEGER) a from SYSIBM.SYSDUMMY1 </selectKey> insert into Author (id, username, password, email,bio, favourite_section) values (#{id}, #{username}, #{password}, #{email}, #{bio}, #{favouriteSection,jdbcType=VARCHAR} ) </insert>
屬性 | 描述 |
---|---|
id | 在命名空間中唯一的標識符,可以被用來引用這條語句。 |
parameterType | 將會傳入這條語句的參數類的完全限定名或別名。 |
flushCache | 將其設置為 true,不論語句什么時候被帶哦用,都會導致緩存被清 空。默認值:false。 |
timeout | 這個設置驅動程序等待數據庫返回請求結果, 並拋出異常時間的最 大等待值。默認不設置(驅動自行處理)。 |
statementType | STA TEMENT,PREPARED 或 CALLABLE 的一種。這會讓 MyBatis 使用選擇使用 Statement,PreparedStatement 或 CallableStatement。 默認值:PREPARED。 |
useGeneratedKeys | ( 僅 對 insert 有 用 ) 這 會 告 訴 MyBatis 使 用 JDBC 的 getGeneratedKeys 方法來取出由數據(比如:像 MySQL 和 SQL Server 這樣的數據庫管理系統的自動遞增字段)內部生成的主鍵。 默認值:false。 |
keyProperty | (僅對 insert 有用) 標記一個屬性, MyBatis 會通過 getGeneratedKeys 或者通過 insert 語句的 selectKey 子元素設置它的值。 默認: 不設置。 |
keyColumn | (僅對 insert 有用) 標記一個屬性, MyBatis 會通過 getGeneratedKeys 或者通過 insert 語句的 selectKey 子元素設置它的值。 默認: 不設置。 |
3.parameter(參數)
我們可以向#{id},#{name}這樣形式的語句轉入參數,但我們還可以更加具體地聲明參數的java類型,jdbc類型,以及使用哪個TypeHandler,對於jdbc類型是NUMERIC的參數,還可以指定他的小數位數,如:
#{age,javaType=int,jdbcType=NUMERIC,numbericScale=2,typeHandler=MyTypeHandler}
除了這些外,還可以聲明參數是IN,OUT或INOUT模式
#{age,javaType=int,jdbcType=NUMERIC,numbericScale=2,typeHandler=MyTypeHandler,mode=INOUT}
最好,還可以使用${str}形式,把str參數的直接字符串值替換到${str}符號中,這種方式盡量少用,因為這會造成SQL注入的問題。
4.sql元素
這個元素可以被用來定義可重用的 SQL 代碼段,可以包含在其他語句中。比如:
<sql id="userColumns"> id,username,password </sql>
<select id="selectUsers" parameterType="int" resultType="hashmap"> select <include refid="userColumns"/> from some_table where id = #{id} </select>
5.resultMap元素
resultMap的概覽視圖:
- constructor - 類在實例化時,用來注入結果到構造方法中
- idArg - ID 參數;標記結果作為 ID 可以幫助提高整體效能
- arg - 注入到構造方法的一個普通結果
- id – 一個 ID 結果;標記結果作為 ID 可以幫助提高整體效能
- result – 注入到字段或 JavaBean 屬性的普通結果
- association – 一個復雜的類型關聯;許多結果將包成這種類型
- 嵌入結果映射 – 結果映射自身的關聯,或者參考一個
- collection – 復雜類型的集
- 嵌入結果映射 – 結果映射自身的集,或者參考一個
- discriminator – 使用結果值來決定使用哪個結果映射
- case – 基於某些值的結果映射
- 嵌入結果映射 – 這種情形結果也映射它本身,因此可以包含很多相 同的元素,或者它可以參照一個外部的結果映射。
- case – 基於某些值的結果映射
5.1 id、result及constructor
這三個元素使用起來都非常相似的,它們只能用於簡單類型數據。
<id property="id" column="post_id"/> <result property="subject" column="post_subject"/>
這些元素支持的屬性:
屬性 | 描述 |
---|---|
property | 映射到列結果的字段或屬性。如果匹配的是存在的,和給定名稱相同 的 JavaBeans 的屬性,那么就會使用。否則 MyBatis 將會尋找給定名稱 property 的字段。這兩種情形你可以使用通常點式的復雜屬性導航。比如,你 可以這樣映射一些東西: “username” ,或者映射到一些復雜的東西: “address.street.number” 。 |
column | 從數據庫中得到的列名,或者是列名的重命名標簽。這也是通常和會 傳遞給 resultSet.getString(columnName)方法參數中相同的字符串。 |
javaType | 一個 Java 類的完全限定名,或一個類型別名(參加上面內建類型別名 的列表) 。如果你映射到一個 JavaBean,MyBatis 通常可以斷定類型。 然而,如果你映射到的是 HashMap,那么你應該明確地指定 javaType 來保證所需的行為。 |
jdbcType | 在這個表格之后的所支持的 JDBC 類型列表中的類型。JDBC 類型是僅 僅需要對插入,更新和刪除操作可能為空的列進行處理。這是 JDBC jdbcType 的需要,而不是 MyBatis 的。如果你直接使用 JDBC 編程,你需要指定 這個類型-但僅僅對可能為空的值。 |
typeHandler | 我們在前面討論過默認的類型處理器。使用這個屬性,你可以覆蓋默 認的類型處理器。這個屬性值是類的完全限定名或者是一個類型處理 器的實現,或者是類型別名。 |
這些元素的映射支持的JDBC類型有:
BIT | FLOAT | CHAR | TIMESTAMP | OTHER | UNDEFINED |
TINYINT | REAL | VARCHAR | BINARY | BLOG | NVARCHAR |
SMALLINT | DOUBLE | LONGVARCHAR | VARBINARY | CLOB | >NCHAR |
INTEGER | NUMERIC | DATE | LONGVARBINARY | BOOLEAN | NCLOB |
BIGINT | DECIMAL | TIME | NULL | CURSOR | ARRAY |
5.2 association關聯查詢
association關聯查詢用於處理一對一關系,它可以使用兩種方式查詢這個關聯對象:嵌套查詢方式和嵌套結果方式。
5.2.1 嵌套查詢方式
示例:
<resultMap id="blogResult" type="Blog"> <association property="author" column="blog_author_id" javaType="Author" select="selectAuthor"/> </resultMap> <select id="selectBlog" parameterType="int" resultMap="blogResult"> SELECT * FROM BLOG WHERE ID = #{id} </select> <select id="selectAuthor" parameterType="int" resultType="Author"> SELECT * FROM AUTHOR WHERE ID = #{id} </select>
Notice:嵌套查詢的屬性column,表示該關聯對象是通過哪個字段查詢得到的,該字段的值會被當作參數傳遞到嵌套查詢selectAuthor中。
Notice:嵌套查詢方式可以很容易地實現遞歸查詢,而嵌套結果方式是不能實現遞歸查詢的。
5.2.2嵌套結果方式
示例:
<select id="selectBlog" parameterType="int" resultMap="blogResult"> select B.id as blog_id, B.title as blog_title, B.author_id as blog_author_id, A.id as author_id, A.username as author_username, A.password as author_password, A.email as author_email, A.bio as author_bio from Blog B left outer join Author A on B.author_id = A.id where B.id = #{id} </select>
<resultMap id="blogResult" type="Blog"> <id property="id" column="blog_id" /> <result property="title" column="blog_title"/> <association property="author" column="blog_author_id" javaType="Author" resultMap="authorResult"/> </resultMap> <resultMap id="authorResult" type="Author"> <id property="id" column="author_id"/> <result property="username" column="author_username"/> <result property="password" column="author_password"/> <result property="email" column="author_email"/> <result property="bio" column="author_bio"/> </resultMap>
Notice:嵌套結果方式一般對應的是一個多表連接查詢,把查詢出來的結果集映射到關聯對象上。
在多表連接查詢中,一般都會重用resultMap,但連接查詢的結果集的列名要求是不一樣的,association元素提供了一個columnPrefix屬性來解決這個問題。如一篇文章有兩個作者共同完成,一個主編,一個副編。
<select id="selectBlog" parameterType="int" resultMap="blogResult"> select B.id as blog_id, B.title as blog_title, A.id as author_id, A.username as author_username, A.password as author_password, A.email as author_email, A.bio as author_bio, CA.id as co_author_id, CA.username as co_author_username, CA.password as co_author_password, CA.email as co_author_email, CA.bio as co_author_bio from Blog B left outer join Author A on B.author_id = A.id left outer join Author CA on B.co_author_id = CA.id where B.id = #{id} </select>
<resultMap id="authorResult" type="Author"> <id property="id" column="author_id"/> <result property="username" column="author_username"/> <result property="password" column="author_password"/> <result property="email" column="author_email"/> <result property="bio" column="author_bio"/> </resultMap>
<resultMap id="blogResult" type="Blog"> <id property="id" column="blog_id" /> <result property="title" column="blog_title"/> <association property="author" resultMap="authorResult" /> <association property="coAuthor" resultMap="authorResult" columnPrefix="co_" /> </resultMap>
5.3 collection集合映射
集合映射是用於解決一對多的關系模型映射問題。它與關聯映射非常相似,這里主要說明集合映射的一些不同點。
Notice:collection的column屬性表示查詢該集合所需要的列或字段,它會被作為參數傳遞到嵌套查詢中。
這里展示一個例子,如何使用嵌套查詢來實現遞歸查詢:
5.3.1典型的樹型表結構
上圖是Category表的結構圖,其中parent_id是外鍵,它引用同一個表的id字段。這其實就是經典的在同一個表中實現樹型結構。
5.3.2 Category表的數據
5.3.3 配置mybatis的映射文件,實現遞歸查詢
<resultMap id="categoryResultMap" type="Category"> <id column="id" property="id"></id> <result column="name" property="name"></result> <association property="parent" column="parent_id" select="selectCategoryById"></association><!-- 遞歸查詢,只能用select方式 --> <collection property="children" column="id" ofType="Category" javaType="java.util.ArrayList" select="selectCategoryChildren"></collection><!-- 遞歸查詢,只能用select方式 --> </resultMap> <select id="selectAllCategory" resultMap="categoryResultMap"> select * from category; </select> <select id="selectCategoryById" resultMap="categoryResultMap" parameterType="int"> select * from category where id=#{parent_id} </select> <select id="selectCategoryChildren" resultMap="categoryResultMap" parameterType="int"> select * from category where parent_id=#{id} </select>