MyBatis 真正強大之處就在這些映射語句,也就是它的魔力所在。對於它的強大功能,SQL 映射文件的配置卻很是簡單。html
若是您比較SQL 映射文件配置與JDBC 代碼,您很快能夠發現,使用SQL 映射文件配置能夠節省95%的代碼量。MyBatis 被建立來專一於SQL,但又給您本身的實現極大的空間。java
須要配置的基本元素
1. cache – 配置給定模式的緩存mysql
2. cache-ref – 從別的模式中引用一個緩存sql
3. resultMap – 這是最複雜而卻強大的一個元素了,它描述如何從結果集中加載對象數據庫
4. sql – 一個能夠被其餘語句複用的SQL 塊緩存
5. insert – 映射INSERT 語句安全
6. update – 映射UPDATE 語句session
7. delete – 映射DELEETE 語句mybatis
8. select - 映射SELECT語句app
配置注意
SQL 映射XML 文件只有一些基本的元素須要配置,而且要按照下面的順序來定義
寫好SQL語句映射文件後,須要在MyBAtis主配置文件mappers標籤中引用!
例如:
- <mappers>
- <mapper resource="com/accp/mybatis/data/BlogMapper.xml" />
- </mappers>
當Java接口與XML文件在一個相對路徑下時,能夠不在myBatis配置文件的mappers中聲明。
SQL
這個元素能夠被用來定義可重用的SQL代碼段,能夠包含在其餘語句中。
例子請看下面select中例子
SELECT
mybatis select是mybatis 中最經常使用的元素之一。
對簡單的查詢,select 元素的配置是至關簡單的:
- <?xml version="1.0" encoding="UTF-8" ?>
- <!DOCTYPE mapper
- PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
- "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
- <mapper namespace="com.accp.mybatis.model.Blog">
-
-
- <sql id="blog_column">id,title,author_id as authorId</sql>
-
- <select id="selectBlog_as_map" parameterType="int" resultType="hashmap">
- select <include refid="blog_column"/> from Blog where id = #{id}
- </select>
-
- </mapper>
這個語句被稱做selectBlog_as_map,使用一個int (或Integer)類型的參數,並返回一個HashMap類型的對象
#{id}告訴mybatis建立了一個PreparedStatement(預處理語句)參數。
在JDBC中,相似的代碼以下:
- String selectBlog_as_map = 「select * from Blog where id =?」;
- PreparedStatement ps = conn.prepareStatement(selectBlog_as_map);
- ps.setInt(1,id);
測試代碼:
- public static void selectBlogAsMap(int id) {
- SqlSession session = sqlMapper.openSession();
- Map<String, Object> map = session.selectOne("selectBlog_as_map",id);
- System.out.println(map);
- session.close();
- }
SELECT的屬性還有不少的屬性能夠配置,具體的以下:
屬性 |
描述 |
取值 |
默認 |
id |
在這個模式下惟一的標識符,可被其它語句引用 |
|
|
parameterType |
傳給此語句的參數的完整類名或別名 |
|
|
resultType |
語句返回值類型的整類名或別名。注意,若是是集合, 那麼這裏填寫的是集合的項的整類名或別名,而不是集合自己的類名。 (resultType 與resultMap 不能並用) |
|
|
resultMap |
引用的外部resultMap 名。結果集映射是MyBatis 中最強大的特性。 許多複雜的映射均可以輕鬆解決。(resultType 與resultMap 不能並用) |
|
|
flushCache |
若是設爲true,則會在每次語句調用的時候就會清空緩存。select 語句默認設爲false |
true|false |
false |
useCache |
若是設爲true,則語句的結果集將被緩存。select 語句默認設爲false true|false false timeout 設置驅動器在拋出異常前等待迴應的最長時間,默認爲不設值,由驅動器本身決定 |
true|false |
false |
timeout |
設置驅動器在拋出異常前等待迴應的最長時間,默認爲不設值,由驅動器本身決定 |
正整數 |
未設置 |
fetchSize |
設置一個值後,驅動器會在結果集數目達到此數值後, 激發返回,默認爲不設值,由驅動器本身決定 |
正整數 |
驅動器決定 |
statementType |
statement,preparedstatement,callablestatement。 預準備語句、可調用語句 |
STATEMENT PREPARED CALLABLE |
PREPARED |
resultSetType |
forward_only,scroll_sensitive,scroll_insensitive 只轉發,滾動敏感,不區分大小寫的滾動 |
FORWARD_ONLY SCROLL_SENSITIVE SCROLL_INSENSITIVE |
驅動器決定 |
- <?xml version="1.0" encoding="UTF-8" ?>
- <!DOCTYPE mapper
- PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
- "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
- <mapper namespace="com.accp.mybatis.model.Blog">
-
- <insert id="insertBlog" parameterType="Blog">
- insert into Blog
- (id,title,author_id)
- values
- (#{id},#{title},#{authorId})
- </insert>
-
- </mapper>
對於insert若是你的數據庫支持自動生成主鍵的字段(好比 MySQL 和 SQL Server),那麼你能夠設置 useGeneratedKeys=」true」,而後把keyProperty 設成對應的列,就搞定了。
例如Blog表已經對 id 使用了自動生成的列類型,那麼語句以下:
- <?xml version="1.0" encoding="UTF-8" ?>
- <!DOCTYPE mapper
- PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
- "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
- <mapper namespace="com.accp.mybatis.model.Blog">
-
- <insert id="insertBlog" parameterType="Blog" useGeneratedKeys=」true」 keyProperty=」id」>
- insert into Blog
- (title,author_id)
- values
- (#{title},#{authorId})
- </insert>
-
- </mapper>
還可使用selectKey元素。下面例子,使用mysql數據庫nextval('student')爲自定義函數,用來生成一個key。
例如:
- <?xml version="1.0" encoding="UTF-8" ?>
- <!DOCTYPE mapper
- PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
- "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
- <mapper namespace="com.accp.mybatis.model.Blog">
- <insert id="insertBlog" parameterType="Blog" >
- <selectKey keyProperty="studentID" resultType="String" order="BEFORE">
- select nextval('id')
- </selectKey>
- insert into Blog
- (id,title,author_id)
- values
- (#{id},#{title},#{authorId})
- </insert>
- </mapper>
insert語句屬性配置細節:
屬性 |
描述 |
取值 |
默認 |
id |
在這個模式下惟一的標識符,可被其它語句引用 |
|
|
parameterType |
傳給此語句的參數的完整類名或別名 |
|
|
flushCache |
若是設爲true,則會在每次語句調用的時候就會清空緩存。select 語句默認設爲false |
true|false |
false |
useCache |
若是設爲true,則語句的結果集將被緩存。select 語句默認設爲false true|false false timeout 設置驅動器在拋出異常前等待迴應的最長時間,默認爲不設值,由驅動器本身決定 |
true|false |
false |
timeout |
設置驅動器在拋出異常前等待迴應的最長時間,默認爲不設值,由驅動器本身決定 |
正整數 |
未設置 |
fetchSize |
設置一個值後,驅動器會在結果集數目達到此數值後,激發返回,默認爲不設值,由驅動器本身決定 |
正整數 |
驅動器決定 |
statementType |
statement,preparedstatement,callablestatement。 預準備語句、可調用語句 |
STATEMENT PREPARED CALLABLE |
PREPARED |
useGeneratedKeys |
告訴MyBatis 使用JDBC 的getGeneratedKeys 方法來獲取數據庫本身生成的主鍵(MySQL、SQLSERVER 等 關係型數據庫會有自動生成的字段)。默認:false |
true|false |
false |
keyProperty |
標識一個將要被MyBatis 設置進getGeneratedKeys 的key 所返回的值,或者爲insert 語句使用一個selectKey 子元素。 |
|
|
selectKey語句屬性配置細節:
屬性 |
描述 |
取值 |
keyProperty |
selectKey 語句生成結果須要設置的屬性。 |
|
resultType |
生成結果類型,MyBatis 容許使用基本的數據類型,包括String 、int類型。 |
|
order |
能夠設成BEFORE 或者AFTER,若是設爲BEFORE,那它會先選擇主鍵, 而後設置keyProperty,再執行insert語句;若是設爲AFTER,它就先運行insert 語句再運行selectKey 語句, 一般是insert 語句中內部調用數據庫(像Oracle)內嵌的序列機制。 |
BEFORE AFTER |
statementType |
像上面的那樣, MyBatis 支持STATEMENT,PREPARED和CALLABLE 的語句形式, 對應Statement ,PreparedStatement 和CallableStatement 響應 |
STATEMENT PREPARED CALLABLE |
UPDATE,DELETE
update 簡單例子:
- <?xml version="1.0" encoding="UTF-8" ?>
- <!DOCTYPE mapper
- PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
- "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
- <mapper namespace="com.accp.mybatis.model.Blog">
- <update id="updateBlog" parameterType="Blog">
- UPDATE Blog
- SET title = #{title},
- author_id = #{author.id},
- WHERE id = #{id};
- </update>
- </mapper>
delete 簡單例子:
- <delete id="deleteBlog" parameterType="Blog">
- DELETE FROM BLOG WHERE ID = #{id}
- </delete>
update、delete語句屬性配置細節:
屬性 |
描述 |
取值 |
默認 |
id |
在這個模式下惟一的標識符,可被其它語句引用 |
|
|
parameterType |
傳給此語句的參數的完整類名或別名 |
|
|
flushCache |
若是設爲true,則會在每次語句調用的時候就會清空緩存。select 語句默認設爲false |
true|false |
false |
useCache |
若是設爲true,則語句的結果集將被緩存。select 語句默認設爲false true|false false timeout 設置驅動器在拋出異常前等待迴應的最長時間,默認爲不設值,由驅動器本身決定 |
true|false |
false |
timeout |
設置驅動器在拋出異常前等待迴應的最長時間,默認爲不設值,由驅動器本身決定 |
正整數 |
未設置 |
fetchSize |
設置一個值後,驅動器會在結果集數目達到此數值後,激發返回,默認爲不設值,由驅動器本身決定 |
正整數 |
驅動器決定 |
statementType |
statement,preparedstatement,callablestatement。 預準備語句、可調用語句 |
STATEMENT PREPARED CALLABLE |
PREPARED |
Parameters
這個元素說的直白點就是定義參數。注意一個語句中只能有一個參數。
因此參數類型在之後的使用中,可能須要複雜的類型,好比hashmap,一個複雜的對象等。例如:
- <?xml version="1.0" encoding="UTF-8" ?>
- <!DOCTYPE mapper
- PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
- "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
- <mapper namespace="com.accp.mybatis.model.Blog">
-
- <insert id="insertBlog" parameterType="Blog">
- insert into Blog
- (id,title,author_id)
- values
- (#{id},#{title},#{author.id})
- </insert>
- </mapper>
若是blog類型的參數對象傳遞到了語句中,id、title和author屬性將會被查找,而後它們的值就被傳遞到預處理語句的參數中。
這點對於傳遞參數到語句中很是好。可是對於參數映射也有一些其餘的特性。
首先,像MyBatis的其餘部分,參數能夠指定一個肯定的數據類型。
- #{property,javaType=int,jdbcType=NUMERIC}
像MyBatis的剩餘部分,javaType一般能夠從參數對象中來肯定,除非對象是一個HashMap。那麼javaType應該被肯定來保證使用正確類型處理器。
注意:若是null被看成值來傳遞,對於全部可能爲空的列,JDBC Type是須要的。也能夠經過閱讀PreparedStatement. setNull()方法的JavaDocs文檔來研究它。
爲了之後自定義類型處理器,你能夠指定一個肯定的類型處理器類(或別名),好比:
- #{age,javaType=int,jdbcType=NUMERIC,typeHandler=MyTypeHandler}
儘管它看起來繁瑣,可是其實是你不多設置它們其中之一。
對於數值類型,對於決定有多少數字是相關的,有一個數值範圍。
- #{height,javaType=double,jdbcType=NUMERIC,numericScale=2}
mode 屬性容許你指定IN,OUT或INOUT參數。若是參數爲OUT或INOUT,參數對象屬性的真實值將會被改變,就像你指望你須要你個輸出參數。若是 mode爲OUT(或INOUT),並且jdbcType爲CURSOR(也就是Oracle的REFCURSOR),你必須指定一個resultMap 來映射結果集到參數類型。要注意這裏的javaType屬性是可選的,若是左邊的空白是jdbcType的CURSOR類型,它會自動地被設置爲結果集。
- #{department,
- mode=OUT,
- jdbcType=CURSOR,
- javaType=ResultSet,
- resultMap=departmentResultMap}
字符串替換
默認狀況下,使用#{}格式的語法會致使MyBatis建立預處理語句屬性並以它爲背景設置安全的值(好比?)。這樣作很安全,很迅速,也是首選的作法,有時你只是想直接在SQL語句中插入一個不改變的字符串。好比,像ORDER BY,你能夠這樣來使用:
ORDER BY ${columnName}
這裏MyBatis不會修改或轉義字符串。
重要:接受從用戶輸出的內容並提供給語句中不變的字符串,這樣作是不安全的。這會致使潛在的SQL注入攻擊,所以你不該該容許用戶輸入這些字段,或者一般自行轉義並檢查。
resultMap
resultMap 元素是MyBatis中最重要最強大的元素。它就是讓你遠離90%的須要從結果集中取出數據的JDBC代碼的那東西,並且在一些情形下容許你作一些JDBC不支持的事情。事實上,編寫類似於對複雜語句聯合映射這些等同的代碼,也許能夠跨過上千行的代碼。ResultMap的設計就是簡單語句不須要明確的結果映射,而不少複雜語句確實須要描述它們的關係。
- package com.accp.mybatis.model;
-
- public class Blog {
- private Integer id;
- private String title;
- private Integer authorId;
-
- }
基於JavaBean的規範,上面這個類有3個屬性:id,title和authorId。這些在select語句中會精確匹配到列名。
這樣的一個JavaBean能夠被映射到結果集,就像映射到HashMap同樣簡單。
- <?xml version="1.0" encoding="UTF-8" ?>
- <!DOCTYPE mapper
- PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
- "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
- <mapper namespace="com.accp.mybatis.model.Blog">
-
- <select id="selectBlog_by_id" parameterType="int" resultType="Blog">
- select * from Blog where id = #{id}
- </select>
-
- </mapper>
這些狀況下,MyBatis會在幕後自動建立一個ResultMap,基於屬性名來映射列到JavaBean的屬性上。若是列名沒有精確匹配,你能夠在列名上使用select字句的別名(一個標準的SQL特性)來匹配標籤。
ResultMap最優秀的地方你已經瞭解了不少了,可是你尚未真正的看到一個。只是出於示例的緣由,讓咱們來看看最後一個示例中外部的resultMap是什麼樣子的,這也是解決列名不匹配的另一種方式。
- <resultMap id="Blog_result" type="Blog" >
- <id column="id" property="id" />
- <result column="title" property="title"/>
- <result column="author_id" property="authorId"/>
- </resultMap>
引用它的語句使用resultMap屬性就好了(注意咱們去掉了resultType屬性)。好比:
- <?xml version="1.0" encoding="UTF-8" ?>
- <!DOCTYPE mapper
- PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
- "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
- <mapper namespace="com.accp.mybatis.model.Blog">
-
-
- <resultMap id="Blog_result" type="Blog" >
- <id column="id" property="id" />
- <result column="title" property="title"/>
- <result column="author_id" property="authorId"/>
- </resultMap>
-
-
- <select id="selectBlog_by_id" parameterType="int" resultMap="Blog_result">
- select * from Blog where id = #{id}
- </select>
-
- </mapper>