Java EE輕量級(jí)框架應(yīng)用實(shí)戰(zhàn)-SSM框架(Spring MVC+Spring+MyBatis)(第2版)課件 第3、4章 動(dòng)態(tài)SQL語(yǔ)句、MyBatis的關(guān)聯(lián)映射_第1頁(yè)
Java EE輕量級(jí)框架應(yīng)用實(shí)戰(zhàn)-SSM框架(Spring MVC+Spring+MyBatis)(第2版)課件 第3、4章 動(dòng)態(tài)SQL語(yǔ)句、MyBatis的關(guān)聯(lián)映射_第2頁(yè)
Java EE輕量級(jí)框架應(yīng)用實(shí)戰(zhàn)-SSM框架(Spring MVC+Spring+MyBatis)(第2版)課件 第3、4章 動(dòng)態(tài)SQL語(yǔ)句、MyBatis的關(guān)聯(lián)映射_第3頁(yè)
Java EE輕量級(jí)框架應(yīng)用實(shí)戰(zhàn)-SSM框架(Spring MVC+Spring+MyBatis)(第2版)課件 第3、4章 動(dòng)態(tài)SQL語(yǔ)句、MyBatis的關(guān)聯(lián)映射_第4頁(yè)
Java EE輕量級(jí)框架應(yīng)用實(shí)戰(zhàn)-SSM框架(Spring MVC+Spring+MyBatis)(第2版)課件 第3、4章 動(dòng)態(tài)SQL語(yǔ)句、MyBatis的關(guān)聯(lián)映射_第5頁(yè)
已閱讀5頁(yè),還剩102頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

動(dòng)態(tài)SQL語(yǔ)句主要元素使用動(dòng)態(tài)SQL語(yǔ)句實(shí)現(xiàn)多條件查詢使用動(dòng)態(tài)SQL語(yǔ)句實(shí)現(xiàn)更新使用<foreach>元素實(shí)現(xiàn)復(fù)雜查詢使用<bind>元素實(shí)現(xiàn)SQL語(yǔ)句拼接第3章

動(dòng)態(tài)SQL語(yǔ)句2024/1/29回顧與作業(yè)點(diǎn)評(píng)2MyBatis基本要素核心對(duì)象SqlSessionFactoryBuilderSqlSessionFactorySqlSession通過(guò)SqlSession實(shí)例直接運(yùn)行映射的SQL語(yǔ)句基于mapper接口的方式執(zhí)行SQL語(yǔ)句系統(tǒng)核心配置文件propertiestypeAliasesenvironmentsmappersSQL映射文件核心對(duì)象最佳生命周期最佳作用域SqlSessionFactoryBuilder方法體內(nèi)方法體內(nèi)(局部變量)SqlSessionFactory從應(yīng)用服務(wù)啟動(dòng)開始一直到應(yīng)用服務(wù)停止—application整個(gè)應(yīng)用內(nèi)SqlSession一次請(qǐng)求的有效期一次請(qǐng)求的有效期內(nèi)回顧作業(yè)點(diǎn)評(píng)點(diǎn)評(píng)作業(yè)的提交情況和共性問(wèn)題學(xué)習(xí)目標(biāo)/Target3

了解動(dòng)態(tài)SQL語(yǔ)句中的主要元素及其說(shuō)明掌握動(dòng)態(tài)SQL語(yǔ)句中主要元素的使用方法

熟練掌握動(dòng)態(tài)SQL語(yǔ)句的運(yùn)用章節(jié)概述/Summary4在實(shí)際項(xiàng)目的開發(fā)中,開發(fā)人員在使用JDBC或其他持久層框架進(jìn)行開發(fā)時(shí),經(jīng)常需要根據(jù)不同的條件拼接SQL語(yǔ)句,拼接SQL語(yǔ)句時(shí)還要確保不能遺漏必要的空格、標(biāo)點(diǎn)符號(hào)等,這種編程方式給開發(fā)人員帶來(lái)了非常大的不便,而MyBatis提供的SQL語(yǔ)句動(dòng)態(tài)組裝功能,恰能很好的解決這一問(wèn)題。本章將對(duì)MyBatis框架的動(dòng)態(tài)SQL進(jìn)行詳細(xì)講解。

目錄/CONTENTS動(dòng)態(tài)SQL語(yǔ)句主要元素使用<foreach>元素實(shí)現(xiàn)復(fù)雜查詢使用動(dòng)態(tài)SQL語(yǔ)句實(shí)現(xiàn)更新使用動(dòng)態(tài)SQL語(yǔ)句實(shí)現(xiàn)多條件查詢5使用<bind>元素實(shí)現(xiàn)SQL語(yǔ)句拼接14325動(dòng)態(tài)SQL語(yǔ)句

主要元素01第3章動(dòng)態(tài)SQL語(yǔ)句動(dòng)態(tài)SQL有什么作用?動(dòng)態(tài)SQL中的元素7

開發(fā)人員在使用JDBC或其他類似的框架進(jìn)行數(shù)據(jù)庫(kù)開發(fā)時(shí),通常都要根據(jù)需求去手動(dòng)拼裝SQL,這是一個(gè)非常麻煩且痛苦的工作,而MyBatis提供的對(duì)SQL語(yǔ)句動(dòng)態(tài)組裝的功能,恰能很好的解決這一麻煩工作。STEP01

動(dòng)態(tài)SQL是MyBatis的強(qiáng)大特性之一,MyBatis采用了功能強(qiáng)大的基于OGNL(ObjectGraphNavigationLanguage)的表達(dá)式來(lái)完成動(dòng)態(tài)SQL。在MyBatis的映射文件中,開發(fā)人員可通過(guò)動(dòng)態(tài)SQL元素靈活組裝SQL語(yǔ)句,這在很大程度上避免了單一SQL語(yǔ)句的反復(fù)堆砌,提高了SQL語(yǔ)句的復(fù)用性。STEP03使用動(dòng)態(tài)SQL的好處動(dòng)態(tài)SQL中的元素8動(dòng)態(tài)SQL中的元素9

動(dòng)態(tài)SQL是MyBatis的強(qiáng)大特性之一,MyBatis3采用了功能強(qiáng)大的基于OGNL的表達(dá)式來(lái)完成動(dòng)態(tài)SQL。動(dòng)態(tài)SQL主要元素如下表所示:SQL元素說(shuō)明<if>判斷語(yǔ)句,用于單條件分支判斷<choose>(<when>、<otherwise>)相當(dāng)于Java中的switch...case...default語(yǔ)句,用于多條件分支判斷<where>簡(jiǎn)化SQL語(yǔ)句中where的條件判斷。<trim>可以靈活地去除多余的關(guān)鍵字。<set>解決動(dòng)態(tài)更新語(yǔ)句。<foreach>循環(huán)語(yǔ)句,常用于in語(yǔ)句等列舉條件中<bind>從OGNL表達(dá)式中創(chuàng)建一個(gè)變量,并將其綁定到上下文,常用于模糊查詢的sql中動(dòng)態(tài)SQL10基于OGNL表達(dá)式完成多條件查詢等邏輯實(shí)現(xiàn)用于實(shí)現(xiàn)動(dòng)態(tài)SQL的元素主要有iftrimwheresetchoose(when、otherwise)foreach使用動(dòng)態(tài)SQL語(yǔ)句實(shí)現(xiàn)多條件查詢02第3章動(dòng)態(tài)SQL語(yǔ)句STEP01

在MyBatis中,<if>元素是最常用的判斷元素,它類似于Java中的if語(yǔ)句,主要用于實(shí)現(xiàn)某些簡(jiǎn)單的條件判斷。在實(shí)際應(yīng)用中,我們可能會(huì)通過(guò)某個(gè)條件查詢某個(gè)數(shù)據(jù)。例如,要查找某個(gè)客戶的信息,可以通過(guò)姓名或者年齡來(lái)查找客戶,也可以不填寫年齡直接通過(guò)姓名來(lái)查找客戶,還可以都不填寫而查詢出所有客戶,此時(shí)姓名和年齡就是非必須條件。類似于這種情況,在MyBatis中就可以通過(guò)<if>元素來(lái)實(shí)現(xiàn)。STEP03<if>元素的應(yīng)用<if>元素12<if>元素13

在MyBatis中,<if>元素是最常用的判斷語(yǔ)句,它類似于Java中的if語(yǔ)句,主要用于實(shí)現(xiàn)某些簡(jiǎn)單的條件選擇。其基本使用示例如下:select*fromtb_userwhere1=1<iftest="username!=nullandusername!=''"> andusernamelikeconcat('%',#{username},'%')</if><iftest="jobs!=nullandjobs!=''"> andjobs=#{jobs}</if>使用<if>元素對(duì)username和jobs進(jìn)行非空判斷,并動(dòng)態(tài)組裝SQL<if>元素14需求說(shuō)明改造查詢用戶信息列表的演示示例,增加查詢條件用戶角色(根據(jù)角色id查詢)用戶名稱(模糊查詢)演示示例:改造用戶表的查詢操作-多條件查詢<if>元素15當(dāng)傳入用戶角色參數(shù)為空的時(shí)候,檢索結(jié)果為空?正確結(jié)果所有用戶角色下的用戶數(shù)據(jù)原因如何處理if(判斷參數(shù)):實(shí)現(xiàn)簡(jiǎn)單的條件判斷問(wèn)題分析select*fromtb_useru,tb_roler whereu.userRole=r.idandu.userNamelikeCONCAT(‘%’,‘’,‘%’) andu.userRole=null;演示示例

:改造用戶表的查詢操作-if<where>元素16當(dāng)只傳入?yún)?shù):用戶角色,而不傳入?yún)?shù):用戶名稱的時(shí)候,控制臺(tái)報(bào)SQL異常錯(cuò)誤?正確結(jié)果指定用戶角色下的所有用戶數(shù)據(jù)原因如何處理where問(wèn)題分析select*fromtb_userwhereanduserRole=?<where>元素17where簡(jiǎn)化SQL語(yǔ)句中where條件判斷智能處理and和or演示示例:改造用戶表的查詢操作-if+where改造訂單表查詢(if)18需求說(shuō)明改造訂單表的查詢功能,使用動(dòng)態(tài)SQL完善此功能查詢條件商品名稱(模糊查詢)供應(yīng)商id是否付款查詢結(jié)果列列表訂單id、訂單編碼、商品名稱、供應(yīng)商id、供應(yīng)商名稱、訂單金額、是否付款、創(chuàng)建時(shí)間修改SQL語(yǔ)句–使用if完成時(shí)間:15分鐘練習(xí)指導(dǎo)改造供應(yīng)商表查詢(if+where)19需求說(shuō)明改造供應(yīng)商表的查詢功能,使用動(dòng)態(tài)SQL完善此功能查詢條件供應(yīng)商編碼(模糊查詢)供應(yīng)商名稱(模糊查詢)查詢結(jié)果列列表供應(yīng)商id、供應(yīng)商編碼、供應(yīng)商名稱、聯(lián)系人、聯(lián)系電話、傳真、創(chuàng)建時(shí)間修改SQL語(yǔ)句–使用if+where組合完成時(shí)間:15分鐘練習(xí)指導(dǎo)共性問(wèn)題集中講解20常見(jiàn)問(wèn)題及解決辦法代碼規(guī)范問(wèn)題調(diào)試技巧共性問(wèn)題集中講解

<trim>元素用于刪除多余的關(guān)鍵字,它可以直接實(shí)現(xiàn)<where>元素的功能。<trim>元素包含4個(gè)屬性。

<trim>元素

21屬性說(shuō)明prefix

指定給SQL語(yǔ)句增加的前綴prefixOverrides

指定SQL語(yǔ)句中要去掉的前綴字符串suffix

指定給SQL語(yǔ)句增加的后綴suffixOverrides

指定SQL語(yǔ)句中要去掉的后綴字符串<trim>元素22trim屬性prefixsuffixprefixOverridessuffixOverrides更靈活地去除多余關(guān)鍵字替代where和set<selectid="getUserList5"resultType="User"> select*fromtb_user

<trimprefix="where"prefixOverrides="and|or"> <iftest="userName!=nullanduserName!=''"> anduserNamelikeCONCAT('%',#{userName},'%') </if> <iftest="userRole!=null"> anduserRole=#{userRole} </if> </trim></select>

上述配置代碼中,<trim>元素的作用是去除一些多余的前綴字符串,它的prefix屬性代表的是語(yǔ)句的前綴(where),而prefixOverrides屬性代表的是需要去除的前綴字符串(SQL中的“AND”或“OR”)。

<where>、<trim>元素23

在前兩個(gè)小節(jié)的案例中,映射文件中編寫的SQL后面都加入了“where1=1”的條件,那么到底為什么要這么寫呢?如果將where后“1=1”的條件去掉,那么MyBatis所拼接出來(lái)的SQL將會(huì)如下所示:select*fromtb_userwhereandusernamelikeconcat('%',?,'%')

可以看出上面SQL語(yǔ)句明顯存在SQL語(yǔ)法錯(cuò)誤,而加入了條件“1=1”后,既保證了where后面的條件成立,又避免了where后面第一個(gè)詞是and或者or之類的關(guān)鍵詞。不過(guò)“where1=1”這種寫法對(duì)于初學(xué)者來(lái)將不容易理解,并且也不夠雅觀。<where>、<trim>元素24select*fromt_customerwhere1=1<choose><whentest="username!=nullandusername!=''">andusernamelikeconcat('%',#{username},'%')</when><whentest="jobs!=nullandjobs!=''">andjobs=#{jobs}</when><otherwise>andphoneisnotnull</otherwise></choose>

針對(duì)上述情況中“where1=1”,在MyBatis的SQL中就可以使用<where>或<trim>元素進(jìn)行動(dòng)態(tài)處理。<where>會(huì)自動(dòng)判斷SQL語(yǔ)句,只有<where>內(nèi)的條件成立時(shí),才會(huì)在拼接SQL中加入where關(guān)鍵字,否則將不會(huì)添加;還會(huì)去除多余的“AND”或“OR”。<where>元素處理<trim>元素處理<trim>的作用是去除特殊的字符串,它的prefix屬性代表語(yǔ)句的前綴,prefixOverrides屬性代表需要去除的哪些特殊字符串,功能和<where>基本是等效的。動(dòng)態(tài)SQL處理“where1=1”select*fromtb_user<where><iftest="username!=nullandusername!=''">andusernamelikeconcat('%',#{username},'%')</if><iftest="jobs!=nullandjobs!=''">andjobs=#{jobs}</if></where>select*fromtb_user<trimprefix="where"prefixOverrides="and"><iftest="username!=nullandusername!=''">andusernamelikeconcat('%',#{username},'%')</if><iftest="jobs!=nullandjobs!=''">andjobs=#{jobs}</if></trim>STEP01

在使用<if>元素時(shí),只要test屬性中的表達(dá)式為true,就會(huì)執(zhí)行元素中的條件語(yǔ)句,但是在實(shí)際應(yīng)用中,有時(shí)只需要從多個(gè)選項(xiàng)中選擇一個(gè)去執(zhí)行。

例如下面的場(chǎng)景:“當(dāng)客戶名稱不為空,則只根據(jù)客戶名稱進(jìn)行客戶篩選;當(dāng)客戶名稱為空,而客戶職業(yè)不為空,則只根據(jù)客戶職業(yè)進(jìn)行客戶篩選。當(dāng)客戶名稱和客戶職業(yè)都為空,則要求查詢出所有電話不為空的客戶信息?!?/p>

針對(duì)上面情況,使用<if>元素進(jìn)行處理是不合適的。MyBatis提供了<choose>、<when>、<otherwise>元素進(jìn)行處理,這三個(gè)元素往往組合在一起使用,作用相當(dāng)于Java語(yǔ)言中的if…elseif…else。STEP03<choose><when>otherwise>使用場(chǎng)景<choose>、<when>、<otherwise>元素25<choose>、<when>、<otherwise>元素26“當(dāng)客戶名稱不為空,則只根據(jù)客戶名稱進(jìn)行客戶篩選;

當(dāng)客戶名稱為空,而客戶職業(yè)不為空,則只根據(jù)客戶職業(yè)進(jìn)行客戶篩選。

當(dāng)客戶名稱和客戶職業(yè)都為空,則要求查詢出所有電話不為空的客戶信息?!奔僭O(shè)如下場(chǎng)景:

這種情況下,使用<if>元素進(jìn)行處理是非常不合適的。如果使用的是Java語(yǔ)言,這種情況顯然更適合使用switch…case…default語(yǔ)句來(lái)處理,而在SQL中就可以使用<choose>、<when>、<otherwise>元素組合進(jìn)行處理。其基本使用示例如代碼所示:select*fromtb_userwhere1=1<choose><whentest="username!=nullandusername!=''">andusernamelikeconcat('%',#{username},'%')</when><whentest="jobs!=nullandjobs!=''">andjobs=#{jobs}</when><otherwise>andphoneisnotnull</otherwise></choose>使用<choose>及其子元素依次對(duì)條件進(jìn)行非空判斷,并動(dòng)態(tài)組裝SQLchoose(when、otherwise)27choose(when、otherwise)相當(dāng)于Java中switch語(yǔ)句當(dāng)when有條件滿足的時(shí)候,就跳出choose演示示例:改造用戶表的查詢操作-choose<choose> <whentest="條件1">…</when> <whentest="條件2">…</when> <whentest="條件3">…</when> … <otherwise>…</otherwise></choose> 改造供應(yīng)商列表查詢-choose28需求說(shuō)明實(shí)現(xiàn)按條件查詢供應(yīng)商表,查詢條件如下供應(yīng)商編碼(模糊查詢)供應(yīng)商名稱(模糊查詢)供應(yīng)商聯(lián)系人(模糊查詢)創(chuàng)建時(shí)間在本年內(nèi)(時(shí)間范圍)查詢結(jié)果列顯示:供應(yīng)商id、供應(yīng)商編碼、供應(yīng)商名稱、供應(yīng)商聯(lián)系人、創(chuàng)建時(shí)間choose(when、otherwise)完成時(shí)間:15分鐘練習(xí)指導(dǎo)共性問(wèn)題集中講解29常見(jiàn)問(wèn)題及解決辦法代碼規(guī)范問(wèn)題調(diào)試技巧共性問(wèn)題集中講解使用動(dòng)態(tài)SQL語(yǔ)句實(shí)現(xiàn)更新03第3章動(dòng)態(tài)SQL語(yǔ)句<set>元素使用場(chǎng)景

在Hibernate框架中,如果想要更新某一個(gè)對(duì)象,就需要發(fā)送所有的字段給持久化對(duì)象,然而在實(shí)際應(yīng)用中,大多數(shù)情況下都是更新某一個(gè)或幾個(gè)字段。如果更新的每一條數(shù)據(jù)都要將其所有的屬性都更新一遍,那么執(zhí)行效率是非常差的。為了解決更新數(shù)據(jù)的效率問(wèn)題,MyBatis提供了<set>元素。<set>元素主要用于更新操作,它可以在動(dòng)態(tài)SQL語(yǔ)句前輸出一個(gè)SET關(guān)鍵字,并將SQL語(yǔ)句中最后一個(gè)多余的逗號(hào)去除。<set>元素與<if>元素結(jié)合可以只更新需要更新的字段。

更新操作31<set>元素32select*fromt_customerwhere1=1<choose><whentest="username!=nullandusername!=''">andusernamelikeconcat('%',#{username},'%')</when><whentest="jobs!=nullandjobs!=''">andjobs=#{jobs}</when><otherwise>andphoneisnotnull</otherwise></choose>

在Hibernate中,想要更新某個(gè)對(duì)象,就需要發(fā)送所有的字段給持久化對(duì)象,這種想更新的每一條數(shù)據(jù)都要將其所有的屬性都更新一遍的方法,其執(zhí)行效率是非常差的。為此,在MyBatis中可以使用動(dòng)態(tài)SQL中的<set>元素進(jìn)行處理:<updateid="update"parameterType=“User">updatetb_user<set><iftest="username!=nullandusername!=''">username=#{username},</if><iftest="jobs!=nullandjobs!=''">jobs=#{jobs},</if></set>whereid=#{id}</update>使用<set>和<if>元素對(duì)username和jobs進(jìn)行更新判斷,并動(dòng)態(tài)組裝SQL。這樣就只需要傳入想要更新的字段即可<set>元素字段非空

在映射文件中使用<set>元素和<if>元素組合進(jìn)行update語(yǔ)句動(dòng)態(tài)SQL組裝時(shí),如果<set>元素內(nèi)包含的內(nèi)容都為空,則會(huì)出現(xiàn)SQL語(yǔ)法錯(cuò)誤。因此,在使用<set>元素進(jìn)行字段信息更新時(shí),要確保傳入的更新字段不能都為空。更新操作33set34更新用戶表數(shù)據(jù)時(shí),若某個(gè)參數(shù)為null時(shí),會(huì)導(dǎo)致更新錯(cuò)誤正確結(jié)果若某個(gè)參數(shù)為null,則不需要更新,保持?jǐn)?shù)據(jù)庫(kù)原值原因SQL語(yǔ)句如何處理ifset演示示例:改造用戶表的修改操作-if+set指導(dǎo)注意技能訓(xùn)練—改造供應(yīng)商表修改操作(if+set)35需求說(shuō)明改造供應(yīng)商表的修改功能,使用動(dòng)態(tài)SQL完善此功能修改SQL語(yǔ)句–使用if+set組合完成時(shí)間:15分鐘練習(xí)指導(dǎo)共性問(wèn)題集中講解36常見(jiàn)問(wèn)題及解決辦法代碼規(guī)范問(wèn)題調(diào)試技巧共性問(wèn)題集中講解使用<trim>元素更新

除了使用<set>元素外,還可以通過(guò)<trim>元素來(lái)實(shí)現(xiàn)更新操作。其中,<trim>元素的prefix屬性指定要添加的<trim>元素所包含內(nèi)容的前綴為set,suffixOverrides屬性指定去除的<trim>元素所包含內(nèi)容的后綴為逗號(hào)。更新操作37trim38if+trim使用if+trim替代if+set進(jìn)行更新用戶表數(shù)據(jù),效果一樣演示示例:改造用戶表的修改操作-if+trim<updateid="modify"parameterType="User">updatetb_user<trimprefix="set"suffixOverrides=","suffix="whereid=#{id}"> <iftest="userCode!=null">userCode=#{userCode},</if> <iftest="userName!=null">userCode=#{userName},</if> <iftest="userPassword!=null">userPassword=#{userPassword},</if></trim></update>示例改造供應(yīng)商表修改操作(if+trim)39需求說(shuō)明改造供應(yīng)商表的修改功能,使用動(dòng)態(tài)SQL完善此功能修改SQL語(yǔ)句–使用if+trim組合完成時(shí)間:15分鐘練習(xí)指導(dǎo)共性問(wèn)題集中講解40常見(jiàn)問(wèn)題及解決辦法代碼規(guī)范問(wèn)題調(diào)試技巧共性問(wèn)題集中講解使用<foreach>元素實(shí)現(xiàn)復(fù)雜查詢04第3章動(dòng)態(tài)SQL語(yǔ)句<foreach>元素42select*fromt_customerwhere1=1<choose><whentest="username!=nullandusername!=''">andusernamelikeconcat('%',#{username},'%')</when><whentest="jobs!=nullandjobs!=''">andjobs=#{jobs}</when><otherwise>andphoneisnotnull</otherwise></choose>

在一個(gè)客戶表中有1000條數(shù)據(jù),現(xiàn)在需要將id值小于100的客戶信息全部查詢出來(lái),這要怎么做呢?假設(shè)如下需求:一條一條的查詢1在Java中用for循環(huán)查詢2那如果要查詢1000條數(shù)據(jù)呢,豈不是很累?考慮過(guò)N條查詢語(yǔ)句時(shí)的查詢效率了嗎?<foreach>元素43foreach迭代一個(gè)集合,通常用于in條件屬性itemindexcollection:必須指定listarraymap-keyopenseparatorclose<foreach>元素的屬性

44屬性說(shuō)明item

表示集合中每一個(gè)元素進(jìn)行迭代時(shí)的別名。該屬性為必選。index在List和數(shù)組中,index是元素的序號(hào),在Map中,index是元素的key。該屬性可選。open

表示foreach語(yǔ)句代碼的開始符號(hào),一般和close=“)”合用。常用在in條件語(yǔ)句中。該屬性可選。separator

表示元素之間的分隔符,例如,在條件語(yǔ)句中,separator=“,”會(huì)自動(dòng)在元素中間用“,”隔開,避免手動(dòng)輸入逗號(hào)導(dǎo)致SQL錯(cuò)誤,錯(cuò)誤示例如in(1,2,)。該屬性可選。close表示foreach語(yǔ)句代碼的關(guān)閉符號(hào),一般和open="("合用。常用在in條件語(yǔ)句中。該屬性可選。collection用于指定遍歷參數(shù)的類型。注意,該屬性必須指定,不同情況下,該屬性的值是不一樣的。

<foreach>元素45需求說(shuō)明:指定用戶角色(1-n個(gè)),獲取這些用戶角色下的用戶列表信息查詢SQL語(yǔ)句含有in條件使用foreach實(shí)現(xiàn)參數(shù):用戶角色列表參數(shù)類型:數(shù)組演示示例:獲取指定用戶角色下用戶列表-foreach_array分析select*fromtb_user whereuserRolein(參數(shù)1,參數(shù)2,參數(shù)3…);<foreach>元素46

針對(duì)上述需求,理想的解決方法就是使用MyBatis中動(dòng)態(tài)SQL的<foreach>元素進(jìn)行處理。其基本使用示例如下所示:<selectid="findUserByIds"parameterType="List"resultType=“User">select*fromtb_userwhereidin<foreachitem="id"index="index"collection="list"open="("separator=","close=")">#{id}</foreach></select><foreach>元素47

關(guān)于上述示例中<foreach>元素中使用的幾種屬性的描述具體如下:<foreach>主要屬性item:配置的是循環(huán)中當(dāng)前的元素。collection:配置的list是傳遞過(guò)來(lái)的參數(shù)類型(首字母小寫),它可以是一個(gè)array、list(或collection)、Map集合的鍵、POJO包裝類中數(shù)組或集合類型的屬性名等。index:配置的是當(dāng)前元素在集合的位置下標(biāo)。separator:配置的是各個(gè)元素的間隔符。open和close:配置的是以什么符號(hào)將這些集合元素包裝起來(lái)。在遍歷參數(shù)時(shí),<collection>屬性的值是必須指定的。不同情況下,該屬性的取值也是不一樣的,主要有以下三種情況。List類型

若入?yún)閱螀?shù)且參數(shù)類型是一個(gè)List,collection屬性值為list。數(shù)組類型若入?yún)閱螀?shù)且參數(shù)類型是一個(gè)數(shù)組,collection屬性值為array。Map類型

若傳入?yún)?shù)為多參數(shù),就需要把參數(shù)封裝為一個(gè)Map進(jìn)行處理,collection屬性值為Map。<collection>屬性的取值48<foreach>元素49

在使用<foreach>時(shí)最關(guān)鍵也是最容易出錯(cuò)的就是collection屬性,該屬性是必須指定的,而且在不同情況下,該屬性的值是不一樣的。主要有以下3種情況:如果傳入的是單參數(shù)且參數(shù)類型是一個(gè)數(shù)組或者List的時(shí)候,collection屬性值分別為array和list(或collection)。1如果傳入的參數(shù)是多個(gè)的時(shí)候,就需要把它們封裝成一個(gè)Map了,當(dāng)然單參數(shù)也可以封裝成Map集合,這時(shí)候collection屬性值就為Map的鍵。2如果傳入的參數(shù)是POJO包裝類的時(shí)候,collection屬性值就為該包裝類中需要進(jìn)行遍歷的數(shù)組或集合的屬性名。3<foreach>元素50需求說(shuō)明:改造上一個(gè)演示示例,使用foreach實(shí)現(xiàn),參數(shù)類型改為L(zhǎng)ist演示示例:獲取指定用戶角色下用戶列表-foreach_list獲取指定供應(yīng)商列表下的訂單列表51需求說(shuō)明指定供應(yīng)商列表(1-n個(gè)),獲取這些供應(yīng)商下的訂單列表信息要求使用foreach實(shí)現(xiàn),參數(shù)類型為數(shù)組完成之后,把參數(shù)類型改為L(zhǎng)ist實(shí)現(xiàn)此功能完成時(shí)間:20分鐘練習(xí)共性問(wèn)題集中講解52常見(jiàn)問(wèn)題及解決辦法代碼規(guī)范問(wèn)題調(diào)試技巧共性問(wèn)題集中講解<foreach>元素53需求說(shuō)明:在上一個(gè)演示示例中,增加一個(gè)參數(shù):gender,要求查詢出指定性別和用戶角色列表下的用戶列表多參數(shù)封裝成Map單參數(shù)也可封裝成Map嗎?演示示例:獲取多參數(shù)下用戶列表-foreach_map分析問(wèn)題思考獲取多參數(shù)下的訂單列表54需求說(shuō)明:根據(jù)訂單編碼(模糊查詢),指定供應(yīng)商列表(1-n個(gè)),獲取相應(yīng)的訂單列表信息多參數(shù)封裝成Map完成時(shí)間:30分鐘練習(xí)指導(dǎo)共性問(wèn)題集中講解55常見(jiàn)問(wèn)題及解決辦法代碼規(guī)范問(wèn)題調(diào)試技巧共性問(wèn)題集中講解使用<bind>元素實(shí)現(xiàn)SQL語(yǔ)句拼接05第3章動(dòng)態(tài)SQL語(yǔ)句<bind>元素57

還記得入門案例中模糊查詢的SQL語(yǔ)句么?select*fromtb_userwhereusernamelike'%${value}%'上述SQL語(yǔ)句有什么不妥?2如果使用“${}”進(jìn)行字符串拼接,則無(wú)法防止SQL注入問(wèn)題;如果改用concat函數(shù)進(jìn)行拼接,則只針對(duì)MySQL數(shù)據(jù)庫(kù)有效;3如果改用“||”進(jìn)行字符串拼接,則只針對(duì)Oracle數(shù)據(jù)庫(kù)有效。1小提示:這樣,映射文件中的SQL就要根據(jù)不同的情況提供不同形式的實(shí)現(xiàn),這顯然是比較麻煩的,且不利于項(xiàng)目的移植。為了減少這種麻煩,就可以使用MyBatis的<bind>元素來(lái)解決這一問(wèn)題。<bind>元素58MyBatis的<bind>元素可以通過(guò)OGNL表達(dá)式來(lái)創(chuàng)建一個(gè)上下文變量,其使用方式如下:<!--<bind>元素的使用:根據(jù)用戶名模糊查詢用戶信息--><selectid="findUserByName"parameterType="User"resultType="User"> <!--_parameter.getUsername()也可直接寫成傳入的字段屬性名,即username--> <bindname="pattern_username"value="'%'+_parameter.getUserName()+'%'"/> select*fromtb_user whereusernamelike#{pattern_username}</select>_parameter.getUsername()表示傳遞進(jìn)來(lái)的參數(shù)(也可以直接寫成對(duì)應(yīng)的參數(shù)變量名,如username)需要的地方直接引用<bind>元素的name屬性值即可本章小結(jié)

本章主要講解了動(dòng)態(tài)SQL相關(guān)知識(shí)。首先講解了動(dòng)態(tài)SQL中的元素;其次講解了條件查詢操作,包括<if>元素、<choose>元素、<when>元素、<otherwise>元素、<where>元素和<trim>元素的使用;然后講解了更新操作;最后講解了復(fù)雜查詢操作。通過(guò)本章的學(xué)習(xí),讀者可以了解常用動(dòng)態(tài)SQL元素的主要作用,并能夠掌握這些元素在實(shí)際開發(fā)中的應(yīng)用。在MyBatis框架中,這些動(dòng)態(tài)SQL元素十分重要,熟練的掌握它們能夠極大地提高開發(fā)效率。

本章小結(jié)59總結(jié)60if+setif-whereif+trimchoose(when、otherwise)foreachMyBatis-動(dòng)態(tài)SQLitemidexcollectionopenseparatorcloselistarraymap本章作業(yè)?

本章作業(yè)請(qǐng)簡(jiǎn)述MyBatis框架動(dòng)態(tài)SQL中的主要元素及其作用。請(qǐng)簡(jiǎn)述MyBatis框架動(dòng)態(tài)SQL中<foreach>元素collection屬性的注意事項(xiàng)。?預(yù)習(xí)作業(yè)不同對(duì)象之間有哪幾種關(guān)聯(lián)方式?MyBatis關(guān)聯(lián)查詢的方式有哪些?61問(wèn)題及作業(yè)集中問(wèn)題&課后作業(yè)62關(guān)聯(lián)映射一對(duì)一一對(duì)多多對(duì)多<resultMap>元素自動(dòng)映射級(jí)別第4章

MyBatis的關(guān)聯(lián)映射2024/1/29學(xué)習(xí)目標(biāo)/Target64了解表之間及對(duì)象之間的關(guān)聯(lián)關(guān)系熟悉關(guān)聯(lián)關(guān)系中的嵌套查詢和嵌套結(jié)果掌握一對(duì)一、一對(duì)多和多對(duì)多關(guān)聯(lián)映射的使用方法章節(jié)概述/Summary65通過(guò)前面幾章介紹了MyBatis的基本用法、關(guān)聯(lián)映射和動(dòng)態(tài)SQL等重要知識(shí),但這些知識(shí)只是針對(duì)單表實(shí)現(xiàn)進(jìn)行操作的,在實(shí)際開發(fā)中,對(duì)數(shù)據(jù)庫(kù)的操作常常會(huì)涉及到多張表,針對(duì)多表之間的操作,MyBatis提供了關(guān)聯(lián)映射,通過(guò)關(guān)聯(lián)映射可以很好地處理表與表、對(duì)象與對(duì)象之間的關(guān)聯(lián)關(guān)系。此外,在實(shí)際開發(fā)中經(jīng)常需要合理地利用MyBatis緩存來(lái)加快數(shù)據(jù)庫(kù)查詢,進(jìn)而有效地提升數(shù)據(jù)庫(kù)性能。本章將對(duì)MyBatis的關(guān)聯(lián)映射以及MyBatis緩存機(jī)制進(jìn)行詳細(xì)講解。

目錄/CONTENTS關(guān)聯(lián)映射多對(duì)多一對(duì)多一對(duì)一66<resultMap>元素自動(dòng)映射級(jí)別14325關(guān)聯(lián)映射01第4章MyBatis的關(guān)聯(lián)映射為什么學(xué)習(xí)MyBatis關(guān)聯(lián)關(guān)系?關(guān)聯(lián)關(guān)系概述68

實(shí)際的開發(fā)中,對(duì)數(shù)據(jù)庫(kù)的操作常常會(huì)涉及到多張表,這在面向?qū)ο笾芯蜕婕暗搅藢?duì)象與對(duì)象之間的關(guān)聯(lián)關(guān)系。針對(duì)多表之間的操作,MyBatis提供了關(guān)聯(lián)映射,通過(guò)關(guān)聯(lián)映射就可以很好的處理對(duì)象與對(duì)象之間的關(guān)聯(lián)關(guān)系。本章中,將對(duì)MyBatis的關(guān)聯(lián)關(guān)系映射進(jìn)行詳細(xì)的講解。STEP01

在關(guān)系型數(shù)據(jù)庫(kù)中,表與表之間存在著三種關(guān)聯(lián)映射關(guān)系,分別為一對(duì)一關(guān)系、一對(duì)多關(guān)系和多對(duì)多關(guān)系。STEP03關(guān)聯(lián)映射關(guān)系關(guān)聯(lián)映射的概述69一對(duì)一一個(gè)數(shù)據(jù)表中的一條記錄最多可以和另一個(gè)數(shù)據(jù)表中的一條記錄相關(guān)。例如,現(xiàn)實(shí)生活中學(xué)生與校園卡就屬于一對(duì)一的關(guān)系,一個(gè)學(xué)生只能擁有一張校園卡,一張校園卡只能屬于一個(gè)學(xué)生。一對(duì)多主鍵數(shù)據(jù)表中的一條記錄可以和另外一個(gè)數(shù)據(jù)表的多條記錄相關(guān)。但另外一個(gè)數(shù)據(jù)表中的記錄只能與主鍵數(shù)據(jù)表中的某一條記錄相關(guān)。例如,現(xiàn)實(shí)中班級(jí)與學(xué)生的關(guān)系就屬于一對(duì)多的關(guān)系,一個(gè)班級(jí)可以有很多學(xué)生,但一個(gè)學(xué)生只能屬于一個(gè)班級(jí)。多對(duì)多一個(gè)數(shù)據(jù)表中的一條記錄可以與另外一個(gè)數(shù)據(jù)表任意數(shù)量的記錄相關(guān),另外一個(gè)數(shù)據(jù)表中的一條記錄也可以與本數(shù)據(jù)表中任意數(shù)量的記錄相關(guān)。例如,現(xiàn)實(shí)中學(xué)生與教師屬于多對(duì)多的關(guān)系,一名學(xué)生可以由多名教師授課,一名教師可以為多名學(xué)生授課。關(guān)聯(lián)關(guān)系概述70

在關(guān)系型數(shù)據(jù)庫(kù)中,多表之間存在著三種關(guān)聯(lián)關(guān)系,分別為一對(duì)一、一對(duì)多和多對(duì)多,如下圖所示:一對(duì)一一對(duì)多多對(duì)多在任意一方引入對(duì)方主鍵作為外鍵;在“多”的一方,添加“一”的一方的主鍵作為外鍵;產(chǎn)生中間關(guān)系表,引入兩張表的主鍵作為外鍵,兩個(gè)主鍵成為聯(lián)合主鍵或使用新的字段作為主鍵。關(guān)聯(lián)關(guān)系概述71

在Java中,通過(guò)對(duì)象也可以進(jìn)行關(guān)聯(lián)關(guān)系描述,如圖所示:一對(duì)一一對(duì)多多對(duì)多在本類中定義對(duì)方類型的對(duì)象,如A類中定義B類類型的屬性b,B類中定義A類類型的屬性a;一個(gè)A類類型對(duì)應(yīng)多個(gè)B類類型的情況,需要在A類中以集合的方式引入B類類型的對(duì)象,在B類中定義A類類型的屬性a;在A類中定義B類類型的集合,在B類中定義A類類型的集合。一對(duì)一02第4章MyBatis的關(guān)聯(lián)映射一對(duì)一73

在現(xiàn)實(shí)生活中,一對(duì)一關(guān)聯(lián)關(guān)系是十分常見(jiàn)的。例如,一個(gè)人只能有一個(gè)身份證,同時(shí)一個(gè)身份證也只會(huì)對(duì)應(yīng)一個(gè)人。

那么使用MyBatis是怎么處理圖中的這種一對(duì)一關(guān)聯(lián)關(guān)系的呢?

在前面章節(jié)所講解的<resultMap>元素中,包含了一個(gè)<association>子元素,MyBatis就是通過(guò)該元素來(lái)處理一對(duì)一關(guān)聯(lián)關(guān)系的。一對(duì)一74

在<association>元素中,通??梢耘渲靡韵聦傩?property指定映射到的實(shí)體類對(duì)象屬性,與表字段一一對(duì)應(yīng)columnjavaType指定映射到實(shí)體對(duì)象屬性的類型指定表中對(duì)應(yīng)的字段select指定引入嵌套查詢的子SQL語(yǔ)句,該屬性用于關(guān)聯(lián)映射中的嵌套查詢fetchType指定在關(guān)聯(lián)查詢時(shí)是否啟用延遲加載。該屬性有l(wèi)azy和eager兩個(gè)屬性值,默認(rèn)值為lazy(即默認(rèn)關(guān)聯(lián)映射延遲加載)一對(duì)一75MyBatis加載關(guān)聯(lián)關(guān)系對(duì)象主要通過(guò)兩種方式:嵌套查詢和嵌套結(jié)果。

嵌套查詢是通過(guò)執(zhí)行另外一條SQL映射語(yǔ)句來(lái)返回預(yù)期的復(fù)雜類型。

嵌套結(jié)果是使用嵌套結(jié)果映射來(lái)處理重復(fù)的聯(lián)合結(jié)果的子集。第一種第二種嵌套查詢是在查詢SQL中嵌入一個(gè)子查詢SQL;嵌套結(jié)果是一個(gè)嵌套的多表查詢SQL;嵌套查詢會(huì)執(zhí)行多條SQL語(yǔ)句;嵌套結(jié)果只會(huì)執(zhí)行一條復(fù)雜的SQL語(yǔ)句;嵌套查詢SQL語(yǔ)句編寫較為簡(jiǎn)單;嵌套結(jié)果SQL語(yǔ)句編寫比較復(fù)雜;一對(duì)一76

雖然使用嵌套查詢的方式比較簡(jiǎn)單,但是嵌套查詢的方式要執(zhí)行多條SQL語(yǔ)句,這對(duì)于大型數(shù)據(jù)集合和列表展示不是很好,因?yàn)檫@樣可能會(huì)導(dǎo)致成百上千條關(guān)聯(lián)的SQL語(yǔ)句被執(zhí)行,從而極大的消耗數(shù)據(jù)庫(kù)性能并且會(huì)降低查詢效率。那怎么解決這種問(wèn)題呢?一對(duì)一77

使用MyBatis的延遲加載在一定程度上可以降低運(yùn)行消耗并提高查詢效率。MyBatis默認(rèn)沒(méi)有開啟延遲加載,需要在核心配置文件中的<settings>元素內(nèi)進(jìn)行配置,具體配置方式如下:多學(xué)一招:MyBatis延遲加載的配置<settings><settingname="lazyLoadingEnabled"value="true"/><settingname="aggressiveLazyLoading"value="false"/></settings>

在映射文件中,<association>元素和<collection>元素中都已默認(rèn)配置了延遲加載屬性,即默認(rèn)屬性fetchType="lazy"(屬性fetchType="eager"表示立即加載),所以在配置文件中開啟延遲加載后,無(wú)需在映射文件中再做配置。一對(duì)一78

使用<association>元素進(jìn)行一對(duì)一關(guān)聯(lián)映射非常簡(jiǎn)單,只需要參考如下兩種示例配置即可。<resultMaptype="IdCard"id="IdCardById"> <idproperty="id"column="id"/> <resultproperty="userName"column="userName"/> <!--一對(duì)一:association使用select屬性引入另外一條SQL語(yǔ)句--> <associationproperty="user"column="uid"javaType="User"

select="cn.dsscm.dao.UserMapper.findUserById"/></resultMap>算術(shù)運(yùn)算符邏輯運(yùn)算符<resultMaptype="IdCard"id="userRoleResult2"> <idproperty="id"column="id"/> <resultproperty="code"column="code"/> <associationproperty="user"javaType="User"> <idproperty="id"column="cid"/> <resultproperty="userName"column="userName"/> </association></resultMap>嵌套的子查詢類屬性類屬性表字段表字段關(guān)聯(lián)屬性類型方法2:嵌套結(jié)果方法1:嵌套查詢r(jià)esultMap79resultMap屬性id:resultMap的唯一標(biāo)識(shí)type:Java實(shí)體類resultMap子元素id一般對(duì)應(yīng)數(shù)據(jù)庫(kù)中該行的主鍵id,設(shè)置此項(xiàng)可提高M(jìn)yBatis性能result映射到JavaBean的某個(gè)“簡(jiǎn)單類型”屬性association映射到JavaBean的某個(gè)“復(fù)雜類型”屬性,比如JavaBean類collection映射到JavaBean的某個(gè)“復(fù)雜類型”屬性,比如集合resultMap80association復(fù)雜的類型關(guān)聯(lián),一對(duì)一內(nèi)部嵌套映射一個(gè)嵌套JavaBean屬性屬性property:映射數(shù)據(jù)庫(kù)列的實(shí)體對(duì)象的屬性javaType:完整Java類名或者別名resultMap:引用外部resultMap子元素idresultproperty:映射數(shù)據(jù)庫(kù)列的實(shí)體對(duì)象的屬性column:數(shù)據(jù)庫(kù)列名或者別名用戶和身份證間關(guān)聯(lián)-1嵌套查詢

<!--嵌套查詢:通過(guò)執(zhí)行另外一條SQL映射語(yǔ)句來(lái)返回預(yù)期的特殊類型--><selectid="findCodeById"parameterType="Integer"resultMap="IdCardById"> SELECT*FROMtb_idcardWHEREid=#{id}</select><resultMaptype="IdCard"id="IdCardById"> <idproperty="id"column="id"/> <resultproperty="userName"column="userName"/> <!--一對(duì)一:association使用select屬性引入另外一條SQL語(yǔ)句--> <associationproperty="user"column="uid"javaType="User"

select="cn.dsscm.dao.UserMapper.findUserById"/></resultMap><!--根據(jù)id查詢用戶信息--><selectid="findUserById"parameterType="Integer"resultType="User"> SELECT*fromtb_userwhereid=#{id}</select>81用戶和身份證間關(guān)聯(lián)-2嵌套結(jié)果<!--根據(jù)roleId獲取用戶列表associationstart--><resultMaptype="IdCard"id="userRoleResult2"> <idproperty="id"column="id"/> <resultproperty="code"column="code"/> <associationproperty="user"javaType="User"> <idproperty="id"column="cid"/> <resultproperty="userName"column="userName"/> </association></resultMap><selectid="findCodeById2"parameterType="Integer"resultMap="userRoleResult2"> SELECTu.*,c.idcid,c.code FROMtb_useru,tb_idcardc WHEREu.id=c.uid ANDc.uid=#{uid}</select>82用戶和用戶角色關(guān)聯(lián)-183嵌套結(jié)果<!--根據(jù)roleId獲取用戶列表associationstart--><resultMaptype="User"id="userRoleResult"> <idproperty="id"column="id"/> <resultproperty="userCode"column="userCode"/> <resultproperty="userName"column="userName"/> <resultproperty="userRole"column="userRole"/>

<associationproperty="role"javaType="Role"> <idproperty="id"column="r_id"/> <resultproperty="roleCode"column="roleCode"/> <resultproperty="roleName"column="roleName"/> </association></resultMap><selectid="getUserListByRoleId"parameterType="Integer"resultMap="userRoleResult"> selectu.*,r.idasr_id,r.roleCode,r.roleName fromtb_useru,tb_roler whereu.userRole=#{userRole}andu.userRole=r.id</select>用戶和用戶角色關(guān)聯(lián)-284嵌套結(jié)果resultMap實(shí)現(xiàn)association的結(jié)果映射<!--根據(jù)roleId獲取用戶列表associationstart--><resultMaptype="User"id="userRoleResult2"> <idproperty="id"column="id"/> <resultproperty="userCode"column="userCode"/> <resultproperty="userName"column="userName"/> <resultproperty="userRole"column="userRole"/> <associationproperty="role"javaType="Role"resultMap="roleResult"/></resultMap><resultMaptype="Role"id="roleResult"> <idproperty="id"column="r_id"/> <resultproperty="roleCode"column="roleCode"/> <resultproperty="roleName"column="roleName"/></resultMap><selectid="getUserListByRoleId2"parameterType="Integer"resultMap="userRoleResult2"> selectu.*,r.idasr_id,r.roleCode,r.roleNamefromtb_useru,tb_roler whereu.userRole=#{userRole}andu.userRole=r.id</select>實(shí)現(xiàn)訂單表的查詢(association)85需求說(shuō)明:實(shí)現(xiàn)按條件查詢訂單表,查詢條件如下:商品名稱(模糊查詢)供應(yīng)商(供應(yīng)商id)是否付款查詢結(jié)果列顯示:訂單編碼、商品名稱、供應(yīng)商編碼、供應(yīng)商名稱、供應(yīng)商聯(lián)系人、供應(yīng)商聯(lián)系電話、訂單金額、是否付款resultMap中使用association子元素完成內(nèi)部嵌套修改Bill.java,增加復(fù)雜類型屬性:Provider編寫SQL查詢語(yǔ)句(連表查詢)創(chuàng)建resultMap-自定義映射結(jié)果,并在select中引用完成時(shí)間:20分鐘練習(xí)指導(dǎo)共性問(wèn)題集中講解86常見(jiàn)問(wèn)題及解決辦法代碼規(guī)范問(wèn)題調(diào)試技巧共性問(wèn)題集中講解一對(duì)多03第4章MyBatis的關(guān)聯(lián)映射一對(duì)多88

開發(fā)人員接觸更多的關(guān)聯(lián)關(guān)系是一對(duì)多(或多對(duì)一)。例如,一個(gè)用戶可以有多個(gè)訂單,同時(shí)多個(gè)訂單歸一個(gè)用戶所有。

那么使用MyBatis是怎么處理這種一對(duì)多關(guān)聯(lián)關(guān)系的呢?

在前面章節(jié)所講解的<resultMap>元素中,包含了一個(gè)<collection>子元素,MyBatis就是通過(guò)該元素來(lái)處理一對(duì)多關(guān)聯(lián)關(guān)系的。一對(duì)多89ofTypeofType屬性與javaType屬性對(duì)應(yīng),它用于指定實(shí)體對(duì)象中集合類屬性所包含的元素類型。

<collection>子元素的屬性大部分與<association>元素相同,但其還包含一個(gè)特殊屬性--ofType。一對(duì)多90<collection>元素的使用也非常簡(jiǎn)單,同樣可以參考如下兩種示例進(jìn)行配置,具體代碼如下:方法1:嵌套查詢<collectionproperty="users"column="id"ofType="User"select="cn.dsscm.dao.selectUsers"/>方法2:嵌套結(jié)果<collectionproperty="users"ofType="User"> <idproperty="id"column="id"/> <resultproperty="userCode"column="userCode"/> <resultproperty="userName"column="userName"/> <resultproperty="userRole"column="userRole"/></collection>嵌套的子查詢類屬性類屬性表字段表字段關(guān)聯(lián)的集合類屬性類型resultMap91collection復(fù)雜類型集合,一對(duì)多內(nèi)部嵌套映射一個(gè)嵌套結(jié)果集到一個(gè)列表屬性property:映射數(shù)據(jù)庫(kù)列的實(shí)體對(duì)象的屬性ofType:完整Java類名或者別名(集合所包括的類型)resultMap:引用外部resultMap子元素idresultproperty:映射數(shù)據(jù)庫(kù)列的實(shí)體對(duì)象的屬性column:數(shù)據(jù)庫(kù)列名或者別名用戶角色關(guān)聯(lián)用戶信息92嵌套結(jié)果<resultMaptype="Role"id="rolelist"><idproperty="id"column="rid"/><resultproperty="roleName"column="roleName"/><collectionproperty="users"ofType="User"><idproperty="id"column="id"/><resultproperty="userCode"column="userCode"/><resultproperty="userName"column="userName"/><resultproperty="userRole"column="userRole"/></collection></resultMap><selectid="getRole"resultMap="rolelist"> SELECTr.idrid,r.roleName,r.roleCode,u.* FROMtb_roler,tb_useru WHEREr.id=u.userRole <iftest="id>0">ANDr.id=#{id}</if></select>publicclassRole{ ……

privateList<User>users;}商品類型關(guān)聯(lián)商品信息93嵌套結(jié)果<resultMaptype="ProductCategory"id="productlist"><idproperty="id"column="cid"/><resultproperty="name"column="cname"/><collectionproperty="products"ofType="Product"><idproperty="id"column="id"/><resultproperty="name"column="name"/><resultproperty="price"column="price"/><resultproperty="stock"column="stock"/></collection></resultMap><selectid="getProduct"resultMap="productlist"> SELECTc.idcid,cname,p.* FROMtb_product_categoryc,tb_productp WHEREc.id=p.categoryLevel1Id <iftest="id>0">ANDc.id=#{id}</if> ORDERBYc.id</select>publicclassProductCategoryimplementsSerializable{ ……

privateList<Product>products; //省略getter和setter方法}resultMap94如何提高結(jié)果映射的可重用性?collection的resultMap屬性分析問(wèn)題獲取供應(yīng)商及其訂單列表(collection)95需求說(shuō)明:根據(jù)指定的供應(yīng)商(id)查詢出其相關(guān)信息以及其下所有的訂單列表查詢結(jié)果列顯示:供應(yīng)商id、供應(yīng)商編碼、供應(yīng)商名稱、供應(yīng)商聯(lián)系人、供應(yīng)商聯(lián)系電話、訂單列表信息(訂單編碼、商品名稱、訂單金額、是否付款)resultMap中使用collection子元素完成內(nèi)部嵌套修改Provider.java,增加集合類型屬性:List<Bill>billList編寫SQL查詢語(yǔ)句(連表查詢)創(chuàng)建resultMap-自定義映射結(jié)果,并在select中引用完成時(shí)間:20分鐘練習(xí)指導(dǎo)共性問(wèn)題集中講解96常見(jiàn)問(wèn)題及解決辦法代碼規(guī)范問(wèn)題調(diào)試技巧共性問(wèn)題集中講解多對(duì)多04第4章MyBatis的關(guān)聯(lián)映射多對(duì)多98

在實(shí)際項(xiàng)目開發(fā)中,多對(duì)多的關(guān)聯(lián)關(guān)系也是非常常見(jiàn)的。以訂單和商品為例,一個(gè)訂單可以包含多種商品,而一種商品又可以屬于多個(gè)訂單。

在數(shù)據(jù)庫(kù)中,多對(duì)多的關(guān)聯(lián)關(guān)系通常使用一個(gè)中間表來(lái)維護(hù),中間表中的訂單id作為外鍵參照訂單表的id,商品id作為外鍵參照商品表的id。銷售訂單關(guān)聯(lián)訂購(gòu)商品信息-199嵌套查詢

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論