MyBatis學習總結二——SQL映射配置


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元素支持的屬性:

Select Attributes
屬性 描述
id 在命名空間中唯一的標識符,可以被用來引用這條語句。
parameterType 將會傳入這條語句的參數類的完全限定名或別名。
parameterMap 這是引用外部 parameterMap 的已經被廢棄的方法。使用內聯參數 映射和 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>
Insert, Update and Delete Attributes
屬性 描述
id 在命名空間中唯一的標識符,可以被用來引用這條語句。
parameterType 將會傳入這條語句的參數類的完全限定名或別名。
parameterMap 這是引用外部 parameterMap 的已經被廢棄的方法。使用內聯參數 映射和 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 – 基於某些值的結果映射
      • 嵌入結果映射 – 這種情形結果也映射它本身,因此可以包含很多相 同的元素,或者它可以參照一個外部的結果映射。

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表的結構

上圖是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>


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM