MyBatis框架之SQL映射和動(dòng)態(tài)SQL

使用MyBatis實(shí)現(xiàn)條件查詢

1.SQL映射文件:

MyBatis真正的強(qiáng)大之處就在于SQL映射語(yǔ)句,MyBatis專(zhuān)注于SQL,對(duì)于開(kāi)發(fā)人員來(lái)說(shuō)也是極大限度的進(jìn)行SQL調(diào)優(yōu),以保證性能。下面是SQL映射文件的幾個(gè)頂級(jí)元素的配置:

1.mapper:映射文件的根節(jié)點(diǎn),只有一個(gè)屬性namespace(命名空間),作用如下:

????(1)用于區(qū)分不同的mapper,全局唯一。

????(2)綁定DAO接口,即面向接口編程,當(dāng)綁定一個(gè)接口,就不用寫(xiě)此接口的實(shí)現(xiàn)類(lèi),會(huì)通過(guò)接口的完全限定名找到對(duì)應(yīng)的mapper配置來(lái)執(zhí)行SQL語(yǔ)句,所以,namespace的命名必須要寫(xiě)接口的完全限定名。

????2.cache:配置給定命名空間的緩存。

????3.cache-ref:從其他命名空間引用緩存配置。

????4.resultMap:用來(lái)描述數(shù)據(jù)庫(kù)結(jié)果集和對(duì)象的對(duì)應(yīng)關(guān)系。

????5.sql:可以重用的SQL塊,也可以被其他語(yǔ)句引用。

????6.insert:映射插入語(yǔ)句。

????7.update:更新映射語(yǔ)句。

????8.delete:刪除映射語(yǔ)句。

????9.select:映射查詢語(yǔ)句。

2.使用select完成單條件查詢

<select id = "GetUserByName" resultType = "User" parameterType = "string">

  select * from user where name like concat('%',#{name},'%')? ? //按照姓名模糊查詢。

</select>

????這是一個(gè)id為GetUserByName的映射語(yǔ)句,參數(shù)類(lèi)型為string,返回類(lèi)型為User。

#{參數(shù)名}:告訴MyBatis生成的PreparedStatement參數(shù),相對(duì)于JDBC,改參數(shù)被標(biāo)識(shí)為‘?’。

  id:命名空間的唯一標(biāo)識(shí)符,可以被用來(lái)引用這條語(yǔ)句。

  parameterType:表示查詢語(yǔ)句傳入?yún)?shù)的類(lèi)型和完全限定名或別名。支持基礎(chǔ)數(shù)據(jù)類(lèi)型和復(fù)雜數(shù)據(jù)類(lèi)型。上述實(shí)例中傳入的參數(shù)是一個(gè)別名,代表String。

       ? ? ?     別名與Java類(lèi)型映射

別名       映射的類(lèi)型     別名     映射的類(lèi)型    
string   String double Double
byte Byte float Float
long  Long boolean Boolean
short Short date Date
int Integer map Map
integer Integer hashmap HashMap
arraylist ArrayList list List

  resultType:查詢語(yǔ)句返回結(jié)果類(lèi)型的完全限定名或別名。別名使用方式和parameterType是一樣的。

2.使用select完成多條件查詢

  使用復(fù)雜數(shù)據(jù)類(lèi)型,把條件參數(shù)封裝為對(duì)象、Map進(jìn)行入?yún)ⅰ?/p>

  不管什么類(lèi)型的參數(shù),或者多少個(gè)參數(shù),都可以封裝為一個(gè)Map進(jìn)行入?yún)?,通過(guò)Map的key進(jìn)行獲取傳入的值。

1<select id="GetUserByNameAndRoleId" resultType="User"
2 ? ?parameterType="map">
3??? ?select * from smbms_user where userName like
4 ? ?CONCAT('%',#{userName},'%')
5 ? ?and userRole = #{userRole}
6</select>

3.使用resultMap完成查詢結(jié)果的展現(xiàn)

????resultMap:做自定義映射,實(shí)體類(lèi)屬性名和數(shù)據(jù)庫(kù)列名不一致的情況下,并且可以指定要顯示的列,使用靈活 應(yīng)用廣泛。

1<resultMap type="User" id="userMap">
2????<id column="id" property="id"/>
3?? ?<result column="userName" property="Name"/> //字段名和屬性名不一致的情況下。
4</resultMap>

屬性和子節(jié)點(diǎn):

????id:唯一標(biāo)識(shí),此id值用于select元素resultMap屬性的引用。

????type:標(biāo)識(shí)該resultMap的映射結(jié)果類(lèi)型。

????result子節(jié)點(diǎn):標(biāo)識(shí)一些簡(jiǎn)單屬性,其中column屬性代表數(shù)據(jù)庫(kù)的字段名,property代表查詢出來(lái)的字段名映射到pojo類(lèi)的某個(gè)屬性。   

????id子節(jié)點(diǎn):與result子節(jié)點(diǎn)作用一樣,一般表示數(shù)據(jù)庫(kù)的主鍵列。

-------------------------------------------------------------------------------------------------------

resultType和resultMap的對(duì)比如下 :

1.resultType:直接表示返回類(lèi)型, 包括基本數(shù)據(jù)類(lèi)型和復(fù)雜數(shù)據(jù)類(lèi)型。

2.resultMap:外部resultMap定義的引用,通過(guò)對(duì)應(yīng)的外部resultMap的id,表示結(jié)果映射到哪個(gè)resultMap上,一般用于字段名和屬性名不一致的情況,或者需要做復(fù)雜的聯(lián)合查詢以便自由控制映射結(jié)果。

3.兩者的關(guān)聯(lián)

????當(dāng)進(jìn)行查詢時(shí),查詢出來(lái)的每個(gè)字段都會(huì)放在一個(gè)Map里,當(dāng)查詢?cè)胤祷貙傩允莚esultType的時(shí)候,會(huì)將鍵值對(duì)取出賦所指定的屬性。其實(shí)MyBatis的每個(gè)查詢映射的返回類(lèi)型都是resultMap,只是當(dāng)我們使用resultType的時(shí)候,會(huì)自動(dòng)把對(duì)應(yīng)的值賦給所指定的對(duì)象屬性,當(dāng)使用resultMap時(shí)候,因?yàn)閙ap不是很好的表示領(lǐng)域,我們就進(jìn)一步的轉(zhuǎn)化為對(duì)應(yīng)的實(shí)體對(duì)象。resultMap主要作用于復(fù)雜的聯(lián)合查詢上。

注意:resultType和resultMap本質(zhì)是一樣的,都是Map數(shù)據(jù)結(jié)構(gòu),但是二者不能同時(shí)存在。

4.resultMap的自動(dòng)映射級(jí)別:默認(rèn)級(jí)別為PARTIAL,也可以在settings更改值。

1<settings>
2????????<!-- 設(shè)置resultMap的自動(dòng)映射級(jí)別為NONE(禁止自動(dòng)匹配) -->
3??????<setting name = "autoMappingBehavior" value = "NONE">
4</settings>

4.使用MyBatis實(shí)現(xiàn)增刪改操作

1.使用insert完成增加操作

<insert id="add" parameterType="User">
 ?  INSERT INTO user(userName,userCode) VALUES(#{userName},#{userCode})</insert>

2.使用update完成修改操作

<update id="update" parameterType="User">

? ????? UPDATE user SET userName= #{userName},userCode= #{userCode} WHERE id = #{id}? ??

</update>

3.使用delete完成刪除操作

<delete id="User" parameterType="integer">
 ? ? ? ?delete from user
 ? ? ? ?where id = #{id}
</delete>

元素中的屬性:

????id:與select元素id一樣,命名空間的唯一標(biāo)識(shí)符。

????parameterType:傳入?yún)?shù)的類(lèi)型的完全限定名或者別名。

對(duì)于增刪改操作的注意事項(xiàng):

????(1)該類(lèi)型的操作本身默認(rèn)返回執(zhí)行SQL影響的行數(shù),所以DAO層的接口方法返回值一般為int類(lèi)型,最好不要boolean類(lèi)型。

????(2)insert、update、delete元素中均沒(méi)有resultType屬性,只有查詢操作需要對(duì)返回結(jié)果類(lèi)型(resultType/resultMap)進(jìn)行相應(yīng)的指定。

?5.使用@param注解實(shí)現(xiàn)多參數(shù)入?yún)?/strong>

????使用注解用來(lái)傳入多個(gè)參數(shù),相當(dāng)于給該參數(shù)重命名,在SQL映射文件中需要使用#{注解名稱(chēng)}來(lái)傳入?yún)?shù)?!?/p>

public user GetUserByIdAndName(@Param("id") Integer id,@Param("Name") String Name);

????當(dāng)參數(shù)為基礎(chǔ)類(lèi)型時(shí),無(wú)論是多參數(shù)還是單參數(shù),都使用@param注解進(jìn)行參數(shù)的傳遞為好!

使用resultMap實(shí)現(xiàn)高級(jí)結(jié)果映射

1.association:

????映射到JavaBean的某個(gè)復(fù)雜的”數(shù)據(jù)類(lèi)型”屬性,僅處理一對(duì)一的關(guān)聯(lián)關(guān)系。

association的屬性節(jié)點(diǎn):

????property:映射數(shù)據(jù)庫(kù)列的實(shí)體對(duì)象屬性名。

????javaType:完整的java類(lèi)名和限定名。propert所映射的屬性的類(lèi)型。

????子元素:id:一般為映射主鍵,可以提高性能。

????result:

????????column:映射的數(shù)據(jù)庫(kù)的字段名。

????????property:映射的數(shù)據(jù)列對(duì)應(yīng)的實(shí)體對(duì)象屬性。
2.collection:

?  映射到JavaBean的某個(gè)復(fù)雜的”數(shù)據(jù)類(lèi)型”屬性,這個(gè)屬性是一個(gè)集合列表,處理一對(duì)多的關(guān)聯(lián)關(guān)系。

????ofType:完整的java類(lèi)名和限定名。propert所映射的屬性的類(lèi)型。

????其余和association基本一致。

MyBatis緩存

????1.一級(jí)緩存:基于PerpetualCache(MyBatis自帶)的HashMap本地緩存。作用域在Session域內(nèi),當(dāng)session flush或者close之后,該緩存被清空。

????2.二級(jí)緩存:global Cache,超出session范圍之外,可以被所有SqlSession共享。開(kāi)啟它只需在MyBatis的核心配置文件 settings 設(shè)置即可。

????補(bǔ)充:一級(jí)緩存緩存的是SQL語(yǔ)句,二級(jí)緩存緩存的是結(jié)果對(duì)象。

????3.二級(jí)緩存配置:

????(1)開(kāi)啟二級(jí)緩存;

<settings>
        <setting name="cacheEnabled" value = "true"/>
<settings>

????(2)mapper文件中設(shè)置緩存,默認(rèn)是沒(méi)有開(kāi)啟緩存的。作用域是針對(duì)namespace而言的,只在namespace內(nèi)的查詢才能共享這個(gè)cache。

????(3)對(duì)個(gè)別查詢進(jìn)行緩存,單獨(dú)設(shè)置cache:

<select id = "getUser" resultType = "User" useCache = "true">
 ? ?...........
</select>

????補(bǔ)充:對(duì)MyBatis的緩存了解就可以了,對(duì)結(jié)果集做緩存并不是MyBatis所擅長(zhǎng)的,而且性能也不是很好,它專(zhuān)心做的應(yīng)該是SQL映射。

-----------------------------------------------------------------------------------------------------------------------

動(dòng)態(tài)SQL

一、使用動(dòng)態(tài)SQL完成多條件查詢。

????動(dòng)態(tài)SQL基于OGNL的表達(dá)式,我們可以方便的在SQL語(yǔ)句中實(shí)現(xiàn)某些邏輯,用于實(shí)現(xiàn)動(dòng)態(tài)SQL元素如下:

  if:利用if實(shí)現(xiàn)簡(jiǎn)單的條件選擇。

  choose(when,otherwise):相當(dāng)于java中的switch語(yǔ)句,通常與when和otherwise搭配。

  set:解決動(dòng)態(tài)更新語(yǔ)句。

  trim:靈活的去除多余的關(guān)鍵字。

  foreach:迭代一個(gè)集合,通常用于in條件。

二、if+where實(shí)現(xiàn)多條件查詢

????where元素可以智能的處理and 和 or 的多余問(wèn)題, 不需擔(dān)心多余關(guān)鍵字導(dǎo)致語(yǔ)法錯(cuò)誤。

if元素的test用于判斷表達(dá)式是否符合,符合則繼續(xù)拼接SQL語(yǔ)句。

三、if+trim+foreach實(shí)現(xiàn)多條件查詢

(1)trim的屬性:

????prefix:前綴: 作用是通過(guò)自動(dòng)識(shí)別是否有返回值后,在trim包含的內(nèi)容上加上前綴,如上述示例的where。

????suffix:后綴: 作用是在trim包含的內(nèi)容上加上后綴。

????prefixOverrides: 對(duì)于trim包含內(nèi)容的首部進(jìn)行指定內(nèi)容,(如上述示例的 and | or) 的忽略(去余);

????suffixOverrides: 對(duì)于trim包含內(nèi)容的首位部進(jìn)行指定內(nèi)容的忽略。

(2)foreach的屬性:

????item:表示集合中每一個(gè)元素進(jìn)行迭代時(shí)的別名。

????index: 指定一個(gè)名稱(chēng),表示在迭代的過(guò)程中,每次迭代到的位置。

????open:表示該語(yǔ)句以什么開(kāi)始(既然是in條件語(yǔ)句,必然是 ' ( ' 開(kāi)始)

????separator: 表示每次進(jìn)行迭代的時(shí)候以什么符號(hào)作為分隔符(既然是in條件語(yǔ)句,必然是 ' , ' 分隔)

????close:?表示該語(yǔ)句以什么結(jié)束(既然是in條件語(yǔ)句,必然是 ' ) ' 結(jié)束)

????collection:最關(guān)鍵,并且最容易出錯(cuò)的屬性。需注意,該屬性必須指定,不同情況下,該屬性值是不同的,主要有三種情況:

????若傳入的參數(shù)是單參數(shù)且類(lèi)型為一個(gè)List的時(shí)候,屬性值為list;

????若傳入的參數(shù)是單參數(shù)且類(lèi)型為一個(gè)數(shù)組的時(shí)候,屬性值為array;

????若傳入的參數(shù)為多參數(shù)時(shí),就需要封裝為一個(gè)map集合進(jìn)行處理。屬性值為Map的key;

?

使用set更新操作,類(lèi)似于上述示例使用方法:

三、choose(when、otherwise)

????when元素:當(dāng)test屬性中的條件滿足時(shí),就會(huì)輸出when元素中的內(nèi)容,并且當(dāng)when中一旦有條件滿足時(shí),就會(huì)跳出choose,所以只有一個(gè)條件會(huì)被輸出。

????otherwise元素:當(dāng)when中的所有條件都不滿足時(shí),則會(huì)輸出此元素的內(nèi)容。

四、MyBatis實(shí)現(xiàn)分頁(yè)功能

????1.使用聚合函數(shù)獲得總記錄數(shù)-

????2.實(shí)現(xiàn)分頁(yè)通過(guò)limit(起始位置,頁(yè)面顯示量)

補(bǔ)充:起始位置的下標(biāo)? = (當(dāng)前頁(yè)碼 - 1 ) * 頁(yè)面顯示量

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1. 簡(jiǎn)介 1.1 什么是 MyBatis ? MyBatis 是支持定制化 SQL、存儲(chǔ)過(guò)程以及高級(jí)映射的優(yōu)秀的...
    笨鳥(niǎo)慢飛閱讀 6,280評(píng)論 0 4
  • Java數(shù)據(jù)持久化之mybatis 一. mybatis簡(jiǎn)介 1.1 原始的JDBC操作: Java 通過(guò) Jav...
    小Q逛逛閱讀 5,444評(píng)論 0 16
  • 0 “曾經(jīng)滄海難為水,除卻巫山不是云?!币?yàn)轫f從的早逝,讓暮年的多情才子元稹寫(xiě)著這流傳千古的句子。興許沒(méi)有陪到最后...
    紅木婁閱讀 571評(píng)論 0 3
  • 我們對(duì)一些事物致以歉意 情書(shū),分岔的路口,一座幽靜的花園 我們之間,隔著許多意義模糊的詞語(yǔ),比如說(shuō) “灰色”“在哪...
    我是不是蝎大人閱讀 271評(píng)論 0 2
  • 人生,總有一些事要自己做,總有一些路要自己走。生命這段旅程,來(lái)的時(shí)候一個(gè)人來(lái),走的時(shí)候一個(gè)人走,什么也帶不來(lái),什么...
    a放下a閱讀 327評(píng)論 0 1

友情鏈接更多精彩內(nèi)容