深入理解MyBatis的原理(四):映射器的用法
前言:繼續(xù)深入學(xué)習(xí) mybatis 的用法及原理,還是先會用再學(xué)習(xí)原理。
映射器的主要元素有:select、insert、update、delete、parameterMap(即將被刪除,不建議使用)、sql、resultMap、cache、cache-ref
各個(gè)元素的規(guī)則定義:見源碼中的文件?org/apache/ibatis/builder/xml/mybatis-3-mapper.dtd
目錄:
一、select 元素
二、insert 元素
三、update 元素
四、delete 元素
五、參數(shù)
六、SQL 片段重用
七、resultMap 結(jié)果映射集
一、select 元素
1、查詢,select 元素有以下屬性:
id:和 Mapper 的命名空間組合起來必須是唯一的,供給 MyBatis 上下文調(diào)用。
parameterType:查詢參數(shù)類型。一般給出類的全命名,也可以給出類的別名。可以選擇 JavaBean、Map 等復(fù)雜的參數(shù)類型傳遞給 SQL。
resultType:查詢返回?cái)?shù)據(jù)類型。一般給出類的全命名,或者別名,不能和 resultMap 同時(shí)使用。
resultMap:查詢返回映射集的引用,將執(zhí)行強(qiáng)大的映射功能。不能和 resultType 同時(shí)使用。它是 MyBatis 最復(fù)雜的元素,可以自定義映射規(guī)則、級聯(lián)、typeHandle 等。
flushCache:它的作用是在調(diào)用 SQL 后,是否要求 MyBatis 清空之前查詢的本地緩存和二級緩存。取值為 boolean,默認(rèn) false。
useCache:啟動二級緩存的開關(guān),是否要求 MyBatis 將此次結(jié)果緩存。取值為 boolean,默認(rèn) true。
timeout:這是超時(shí)參數(shù),等超時(shí)的時(shí)候?qū)伋霎惓?#xff0c;單位為秒。默認(rèn)值為數(shù)據(jù)庫廠商提供的 JDBC 驅(qū)動所設(shè)置的秒數(shù)。
fetchSize:獲取記錄的總條數(shù)。默認(rèn)值為數(shù)據(jù)庫廠商提供的 JDBC 驅(qū)動所設(shè)置的條數(shù)。
statementType:選擇使用 JDBC 的 Statement 工作,取值為 STATEMENT、PREPARED、CallableStatement。默認(rèn) PREPARED。
resultSetType:很少使用
databaseId:數(shù)據(jù)庫廠商標(biāo)識,提供多數(shù)據(jù)庫的支持。
resultOrdered:很少使用
resultSets:很少使用
2、舉例
dao 接口
/*** 通過名字查找用戶* @param name* @return*/User queryUserByName(String name);xml
<select id="queryUserByName" resultType="com.yule.user.entity.User">select t.id, t.name, t.age from t_user twhere t.name = #{name,jdbcType=VARCHAR}</select>3、自動映射
當(dāng)配置?autoMappingBehavior 不是 NONE 時(shí),MyBatis 會提供自動映射功能,只要返回的 sql 列名(別名)和 JavaBean 的屬性一致,MyBatis 就會幫助我們回填這些字段無需任何配置,它可以在很大程度上簡化我們的配置工作。
在實(shí)際中,通常我們是使用 sql 列名的別名的方式自動映射。上方例子的?resultType="com.yule.user.entity.User" 就是 MyBatis 的自動映射。
在實(shí)際中,也可以通過在配置文件中開啟駝峰命名方式:mapUndersoreToCamlCase 為 true。這種方式的前提是數(shù)據(jù)庫命名是規(guī)范的,即每一個(gè)單詞都用下劃線分割,POJO 采用的是駝峰命名方式,那么可以設(shè)置配置文件,從而達(dá)到從數(shù)據(jù)庫到 POJO 的自動映射了。
自動映射在 MyBatis 的配置文件中,元素 settings 中可以配置 autoMappingBehavior 屬性值來設(shè)置其策略,它包含 3 個(gè)值:
- NONE:取消自動映射
- PARTIAL:只會自動映射,沒有定義嵌套結(jié)果集映射的結(jié)果集。為默認(rèn)值。
- FULL:會自動映射任意復(fù)雜的結(jié)果集(無論是否嵌套),性能會下降。
在大部分的情況下 MyBatis 都會推斷你返回?cái)?shù)據(jù)的類型,所以大部分情況下你都無需去配置參數(shù)類型和結(jié)果類型。要我們設(shè)置的往往只是可能返回為空的字段類型而已。因?yàn)?null 值,MyBatis 無法判斷其類型。
4、傳遞多個(gè)參數(shù)
一、使用 map,缺點(diǎn)是業(yè)務(wù)關(guān)聯(lián)性不強(qiáng),造成代碼可讀性下降。
二、使用注解 @Param,xml 中無需定義參數(shù)類型。可讀性增強(qiáng),但是當(dāng)參數(shù)個(gè)數(shù)太多時(shí),可讀性仍然會下降。
三、使用 JavaBean 傳遞參數(shù)。
這三種方式對比:
- 使用 Map 傳遞參數(shù)。因?yàn)?Map 導(dǎo)致代碼的可讀性下降,會導(dǎo)致后面的擴(kuò)展和維護(hù)比較困難,所以建議少使用這種方式。
- 使用 @Param 注解方式。這種方式可讀性高,但是當(dāng)參數(shù)個(gè)數(shù)很多的時(shí)候,同樣會導(dǎo)致可讀性和維護(hù)性下降,所以,當(dāng)參數(shù)個(gè)數(shù)小于等于 5 時(shí),建議采取這種方式。
- 使用實(shí)體 JavaBean 的方式。當(dāng)參數(shù)個(gè)數(shù)大于 5 時(shí),建議采取這種方式。
5、使用 resultMap 映射結(jié)果集
? 對于簡單的映射,建議采用自動映射就好,可以減少配置。resultMap 映射一般就用于復(fù)雜、級聯(lián)這些關(guān)聯(lián)的配置。所以這個(gè)放在 resultMap 結(jié)果映射集講。
二、insert 元素
1、插入,insert 元素有一下屬性:
id:同 select
parameterType:同 select
flushCache:同 select
timeout:同 select
statemeterType:同 select
keyProperty:表示以哪個(gè)列作為屬性的主鍵。不能和 keyColumn 同時(shí)使用。聯(lián)合主鍵可以用逗號隔開。
useGeneratedKeys:這會令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法來取出數(shù)據(jù)庫內(nèi)部生成的主鍵,使用該屬性后就必須使用keyColumn或者KeyProperty屬性中的一個(gè)。取值為 boolean 值,默認(rèn) false。
keyColumn:指明第幾列是主鍵。不能和 keyProperty 同時(shí)使用。聯(lián)合主鍵可以用逗號隔開。只接受整形參數(shù)。
databaseId:同 select
lang:使用很少
2、舉例
?dao 接口
/*** 新增用戶* @param user* @return*/int insertUser(User user);xml,自定義規(guī)則:使用序列實(shí)現(xiàn)主鍵回填,即執(zhí)行完新增后返回主鍵 id。這個(gè)能把主鍵 id 回填到實(shí)體 User 上去。
MyBatis 中 不允許同事包含連兩個(gè)?selectKey 標(biāo)簽。
<insert id="insertUser"><selectKey keyProperty="id" order="BEFORE" resultType="int">select t_user_s.nextval from dual</selectKey>insert into t_user(id, name, age)values(#{id}, #{name}, #{age})</insert>測試
@Testpublic void testInsertUser(){SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();SqlSession sqlSession = sqlSessionFactory.openSession();UserDao mapper = sqlSession.getMapper(UserDao.class);User user = new User("yule", "24");mapper.insertUser(user);sqlSession.commit();sqlSession.close();System.out.println(user.toString());}3、舉例2
xml,使用主鍵自增長(必須在表中設(shè)置 id 字段為自增字段),同時(shí) sql 執(zhí)行完成之后 MyBatis 自動將執(zhí)行完 sql 后自動生成的 id 回填到我們的參數(shù) User 對象中。
<insert id="insertUser" useGeneratedKeys="true" keyProperty="id">insert into t_user(name, age)values(#{name}, #{age})</insert>三、update 元素
1、修改,和 insert 一樣,MyBatis 執(zhí)行完后會返回一個(gè)整數(shù),標(biāo)出執(zhí)行后影響的條數(shù)。
2、舉例
dao 接口
/*** 修改用戶信息* @param user* @return*/int updateUserById(User user);xml
<update id="updateUserById">update t_user t set t.age = #{age}, t.name = #{name}where t.id = #{id}</update>四、delete 元素
1、刪除,和 insert 一樣,MyBatis 執(zhí)行完后會返回一個(gè)整數(shù),標(biāo)出執(zhí)行后影響的條數(shù)。
2、舉例
dao 接口
int deleteUserById(String id);xml
<delete id="deleteUserById">delete t_user t where t.ID = #{id}</delete>五、參數(shù)?
定義參數(shù)屬性時(shí),MyBatis 不允許換行!!!
1、參數(shù)配置
我們可以通過制定參數(shù)的類型去讓對應(yīng)的 typeHandle 處理它們,也可以通過指定對應(yīng)的 JavaType、JdbcType 來明確使用哪個(gè) typeHandle 處理參數(shù)。詳見?https://www.cnblogs.com/yuxiaole/p/9464019.html#typeHandler
2、存儲過程支持
? 對于存儲過程而言,存在 3 種參數(shù),輸入?yún)?shù)(IN)、輸出參數(shù)(OUT)、輸入輸出參數(shù)(INOUT)。MyBatis 的參數(shù)規(guī)則為其提供了良好的支持。
3、特殊字符串替換和處理(# 和 $)
使用 #{} 方式,MyBatis 會用創(chuàng)建預(yù)編譯的語句,然后 MyBatis 為它設(shè)值。
使用 ${} 方式,傳遞 SQL 語句本身,比如傳遞 SQL 的列名、根據(jù)某些列排序等。比如 select ${columns} from t_tablename 來支持傳遞動態(tài)列名。不過使用這種方式是不安全的,所以雖然 MyBatis 是給了靈活性,但是自己也需要控制參數(shù)來保證 SQL 運(yùn)轉(zhuǎn)的正確性和安全性。
六、SQL 片段重用
采用? <include refid="sql_id"></include> 來實(shí)現(xiàn) SQL 片段的重用。SQL 片段是指用 <sql></sql> 定義的片段。
比如:給 include 標(biāo)簽加一個(gè) refid 屬性進(jìn)行引用,從而達(dá)到重用的功能
<sql id="user_columns">${prefix}.id, ${prefix}.name, ${prefix}.age</sql><select id="queryUserByName" resultType="com.yule.user.entity.User">select<include refid="user_columns"><property name="prefix" value="t"/></include>from t_user twhere t.name = #{name,jdbcType=VARCHAR}</select>或者,可以直接給 refid 一個(gè)參數(shù)值,由程序制定引入 SQL
<select id="queryUserList" resultType="User" ><include refid="common_query"><property name="columnsName" value="user_columns"/></include></select> <sql id="common_query">select<include refid="${columnsName}"><property name="prefix" value="t"/></include>from t_user t</sql>七、resultMap 結(jié)果映射集
resultMap 是 MyBatis 中最復(fù)雜的元素。主要是定義一個(gè)查詢中的結(jié)果集的映射關(guān)系,不支持修改、刪除。作用是定義映射規(guī)則、級聯(lián)的更新、定制類型轉(zhuǎn)換器等。
1、resultMap 元素里面的構(gòu)成
見源碼:org/apache/ibatis/builder/xml/mybatis-3-mapper.dtd
<!ELEMENT resultMap (constructor?,id*,result*,association*,collection*, discriminator?)>其中,constructor 元素用于配置實(shí)體構(gòu)造方法。表示告訴 MyBatis 用實(shí)體的哪個(gè)構(gòu)造方法來構(gòu)造實(shí)體。
<!ELEMENT constructor (idArg*,arg*)>其中,id 元素是表示哪個(gè)列是主鍵,允許多個(gè)主鍵,多個(gè)主鍵稱為聯(lián)合主鍵。
其中,result 元素是配置 POJO 到 SQL 列名的映射關(guān)系。
result 和 id 兩個(gè)元素都有如下屬性:
- property:代表 POJO 的屬性名稱。映射到列結(jié)果的字段或?qū)傩?#xff0c;如果 POJO 的屬性匹配是存在的,和給定 SQL 列名(column 元素)相同的,那么 MyBatis 就會映射到 POJO 上。
- column:對應(yīng)的是 SQL 的列名。
- javaType:配置 Java 的字段類型
- jdbcType:配置數(shù)據(jù)庫中的字段類型
- typeHandle:類型處理器
2、使用 map 存儲結(jié)果集
select 元素中使用 resultMap 會使可讀性下降,所以建議更多時(shí)候使用 POJO 的方式來自動映射,即 resultType。
resultMap 元素的屬性 id 代表這個(gè) resultMap 的標(biāo)識,type 代表需要映射的 POJO。
<!ATTLIST resultMap id CDATA #REQUIRED type CDATA #REQUIRED extends CDATA #IMPLIED autoMapping (true|false) #IMPLIED >舉例:SQL 語句的列名需要和 column 一 一對應(yīng)。
<resultMap id="userResultMap" type="com.yule.user.entity.User"><constructor><idArg column="id" javaType="string"/><arg column="name" javaType="string"/><arg column="age" javaType="string"/></constructor><id property="id" column="id"/><result property="name" column="name"/><result property="age" column="age"/></resultMap> <select id="queryUserById" resultMap="userResultMap">select t.id, t.name, t.age from t_user twhere t.id = #{id}</select>3、級聯(lián)
有 3 中關(guān)系:一對一、一對多、多對多。多對多可用一對多雙向標(biāo)識。
在 MyBatis 中級聯(lián)分為這么 3 種:
- association:一對一。
- collection:一對多。
- discriminator:鑒別器。可以根據(jù)實(shí)際選擇采用哪個(gè)類作為實(shí)例,允許根據(jù)特定的條件去關(guān)聯(lián)不同的結(jié)果集。
舉例:
?
轉(zhuǎn)載于:https://www.cnblogs.com/yuxiaole/p/9478618.html
總結(jié)
以上是生活随笔為你收集整理的深入理解MyBatis的原理(四):映射器的用法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: StarUML 破解方法2.X(转)
- 下一篇: hdu 6406(思路+数据结构)