日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

Mybatis中的collection、association来处理结果映射

發(fā)布時(shí)間:2025/3/19 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Mybatis中的collection、association来处理结果映射 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
前不久的項(xiàng)目時(shí)間緊張,為了盡快完成原型開(kāi)發(fā),寫(xiě)了一段效率相當(dāng)?shù)偷拇a。

最近幾天閑下來(lái),主動(dòng)把之前的代碼優(yōu)化了一下:)

標(biāo)簽:Java、Mybatis、MySQL 概況:本地系統(tǒng)從另外一個(gè)系統(tǒng)得到實(shí)體類(lèi)集合List<UserEvent>,但是實(shí)體中只有eventId信息,其他屬性值均為空。 需要從數(shù)據(jù)庫(kù)中查詢數(shù)據(jù),完善List<UserEvent>的信息并返回。 相關(guān)業(yè)務(wù)表以及對(duì)應(yīng)的實(shí)體類(lèi),如下圖。(為了回避項(xiàng)目信息,相關(guān)業(yè)務(wù)內(nèi)容均省略,以下表名、實(shí)體名、代碼變量名等均用字母ABC代替。)

原處理

1.先來(lái)看代碼,乍一看邏輯清晰,符合正常思維習(xí)慣。 但是仔細(xì)查看發(fā)現(xiàn),for循環(huán)中的每步處理都和數(shù)據(jù)查詢有關(guān)。假設(shè)有10次循環(huán),每次循環(huán)中有4次數(shù)據(jù)庫(kù)連接查詢,一共需要連接數(shù)據(jù)庫(kù)40次。 每次數(shù)據(jù)庫(kù)連接都需要一定的開(kāi)銷(xiāo),隨著循環(huán)量不斷增加,處理時(shí)間將成倍增長(zhǎng),造成資源浪費(fèi)。 1 String eventId = "";2 String aTime = "";3 for (UserEvent event : userEventList) {4 eventId = event.getEventId();5 6 // 獲取業(yè)務(wù)B信息7 List<EntityB> listB = mapperB.selectBInfoByEventId(eventId);8 event.setListB(listB);9 10 // 獲取業(yè)務(wù)C信息 11 List<EntityC> listC = mapperC.selectCInfoByEventId(eventId); 12 event.setListC(listC); 13 14 // 查看是否有業(yè)務(wù)B處理 15 EntityB entityB = mapperB.selectBInfoByPrimary(phone, eventId); 16 event.setIsActionB(null == entityB ? "false" : "true"); 17 18 // 獲取業(yè)務(wù)A和用戶信息 19 User userInfo = mapperA.selectEventUserInfoByEventId(eventId); 20 if(null != userInfo){ 21 aTime = userInfo.getTime(); 22 event.setTime(aTime == null ? "" : sdfMd.format(sdfYmd.parse(aTime))); 23 event.setUserInfo(userInfo); 24 } 25 }

?

2.再來(lái)看查詢語(yǔ)句。 業(yè)務(wù)表A和業(yè)務(wù)表B沒(méi)有復(fù)雜的查詢。只有業(yè)務(wù)表C使用了一個(gè)子查詢,來(lái)獲取表內(nèi)自身數(shù)據(jù)引用的信息。 各業(yè)務(wù)表數(shù)據(jù)都需要關(guān)聯(lián)到用戶表User。 1 <select id="selectBInfoByEventId" parameterType="String" resultType="EntityA">2 SELECT3 B.phone AS phone,4 B.time AS time,5 U.name AS userName6 FROM table_b B7 LEFT JOIN user U ON U.phone = B.phone8 WHERE B.event_id = #{eventId}9 ORDER BY B.time ASC 10 </select> 11 <select id="selectCInfoByEventId" parameterType="String" resultType="EntityC"> 12 SELECT 13 C.cmtId, 14 C.referId, 15 C.time, 16 U.name AS userName 17 ( SELECT TU.name FROM table_c TC 18 LEFT JOIN user TU ON TU.phone = TC.phone 19 WHERE TC.cmt_id = TC.refer_id 20 ) AS referName 21 FROM table_c C 22 LEFT JOIN user U ON C.phone = U.phone 23 WHERE C.event_id = #{eventId} 24 ORDER BY C.time ASC 25 <select id="selectEventUserInfoByEventId" parameterType="java.lang.String" resultType="User"> 26 SELECT 27 U.name, 28 U.picId, 29 A.time 30 FROM table_a A 31 LEFT JOIN user U ON U.phone = A.phone 32 WHERE A.event_id = #{eventId} 33 </select>

?

優(yōu)化分析

  • 在代碼結(jié)構(gòu)上,要避免在for循環(huán)中作查詢處理??紤]將查詢參數(shù)evenId從for循環(huán)中提取出來(lái),做批量查詢,然后再將查詢結(jié)果設(shè)定到對(duì)應(yīng)的實(shí)體類(lèi)中。
  • 在業(yè)務(wù)上,對(duì)于每一個(gè)UserEvent中的eventId,業(yè)務(wù)表A中必定對(duì)應(yīng)有一條記錄,而在業(yè)務(wù)表B和業(yè)務(wù)表C中則未必有與這個(gè)eventId關(guān)聯(lián)的數(shù)據(jù)。因此,可以將業(yè)務(wù)表A作為主表,通過(guò)eventId與另外幾個(gè)表關(guān)聯(lián)查詢。查詢次數(shù)也由原來(lái)的至少四次減少為一次查詢。
  • 對(duì)于聯(lián)合查詢的結(jié)果,以UserEvent作為查詢結(jié)果的實(shí)體類(lèi),使用Mybatis中的collection、association來(lái)處理結(jié)果映射。
  • 另外,各業(yè)務(wù)表的查詢中都有與用戶表User的關(guān)聯(lián),考慮將各業(yè)務(wù)信息的查詢處理創(chuàng)建為視圖。這樣不僅能簡(jiǎn)化聯(lián)合查詢中SQL語(yǔ)句,也可以隔離基礎(chǔ)表的數(shù)據(jù)。
  • ?

    優(yōu)化后的代碼?

    int eventSize = userEventList.size();List<String> eventIds = new ArrayList<String>(); // 如果考慮去掉重復(fù)數(shù)據(jù),可以使用集合Set,但是作為Mybatis的輸入?yún)?shù),最后還是需要將Set轉(zhuǎn)化為L(zhǎng)ist。
    // 此處直接使用List,因?yàn)樵跇I(yè)務(wù)上排除了重復(fù)數(shù)據(jù)的可能性。for (int i = 0; i < eventSize; i++) {eventIds.add(userEventList.get(i).getEventId());}Map<String, Object> paramsMap = new HashMap<String, Object>();paramsMap.put("eventIds", eventIds);paramsMap.put("phone", phone);List<UserEvent> eventInfoList = eventMapper.selectUserEventInfo(paramsMap);// 將查詢結(jié)果轉(zhuǎn)化為Map存儲(chǔ),方便調(diào)用Map<String, UserEvent> eventInfoMap = new HashMap<String, UserEvent>();for(UserEvent event : eventInfoList){eventInfoMap.put(event.getEventId(), event);}UserEvent newEvent = null;String aTime = null;for(UserEvent event : roadEventList){ // 從查詢結(jié)果Map中取出補(bǔ)充信息,保存到原UserEvent對(duì)象中newEvent =eventInfoMap.get(event.getEventId());if(null != newEvent ){aTime = newEvent.getTime();event.setTime(aTime == null ? "" : sdfMd.format(sdfYmd.parse(aTime )));event.setIsActionB(newEvent.getIsActionB() == null ? "false" : newEvent.getIsActionB());event.setUserInfo(newEvent.getUserInfo());event.setListB(newEvent.getListB());event.setListC(newEvent.getListC());}}

    ?

    <resultMap id="UserMap" type="User"><result column="name" property="name" /><result column="picId" property="picId" /><result column="time" property="time" /></resultMap><resultMap id="BMap" type="EntityB"><id column="bPhone" property="phone" /><result column="bUserName" property="userName" /><result column="bTime" property="time" /></resultMap><resultMap id="CMap" type="EntityC"><id column="cmtId" property="cmtId" /><result column="referId" property="referId" /><result column="cUserName" property="userName" /><result column="referName" property="referName" /><result column="cTime" property="time" /></resultMap><resultMap id="EventResultMap" type="com.xxxx.bean.UserEvent"><id column="eventId" property="eventId" /><result column="time" property="time" /><result column="isActionB" property="isActionB" /><association property="userInfo" resultMap="UserMap" /><collection property="listB" resultMap="BMap" /><collection property="listC" resultMap="CMap" /></resultMap><select id="selectUserEventInfo" resultMap="EventResultMap">SELECTA.eventId,A.time,A.name,A.picId,CASE WHEN B.phone = #{phone} THEN "true" ELSE "false" END AS isActionB,B.phone AS bPhone,B.userName AS bUserName,B.time AS bTime,C.cmtId,C.referId,C.userName AS cUserName,C.referName AS referName,C.time AS cTimeFROM v_table_a ALEFT JOIN v_table_b B ON B.eventId = A.eventIdLEFT JOIN v_table_c C ON C.eventId = A.eventId<where>A.event_id in<foreach collection="eventIds" index="" item="eventId"
                open="(" separator="," close=")">#{eventId}</foreach></where>;</select>

    ?

    編碼時(shí)需要注意的幾個(gè)地方

    1. 復(fù)雜對(duì)象的映射解析

    采用resultMap嵌套。其中,collection標(biāo)簽表示映射一個(gè)集合,association標(biāo)簽表示映射一個(gè)實(shí)體類(lèi), 標(biāo)簽中的property屬性值對(duì)應(yīng)的是,該集合/實(shí)體在查詢結(jié)果對(duì)象中的變量名。 對(duì)于各表中名稱相同的字段,需要建立別名,否則解析時(shí)無(wú)法確定各屬性與表字段的對(duì)應(yīng)關(guān)系。 如:業(yè)務(wù)表B和業(yè)務(wù)表C中都有userName字段,在查詢語(yǔ)句中為為字段別名加了前綴來(lái)區(qū)分。 B.userName AS bUserName,?<result?column="bUserName"property="userName"/> C.userName AS cUserName,?<result?column="cUserName"?property="userName"?/> resultMap中type屬性表示標(biāo)簽所包含內(nèi)容對(duì)應(yīng)映射的Java類(lèi)。 該屬性可以寫(xiě)類(lèi)的全路徑(如:<resultMap?id="EventResultMap"?type="com.xxxx.bean.UserEvent">?), 也可以配置為簡(jiǎn)寫(xiě)的類(lèi)名(如:<resultMap?id="UserMap"?type="User">?)。 簡(jiǎn)寫(xiě)的類(lèi)名需要在xml配置文件中設(shè)置(如下),配好之后的簡(jiǎn)寫(xiě)類(lèi)名可以在各個(gè)sql.xml中使用。 <!-- spring-mybatis.xml文件 --><!-- 配置sqlSessionFactory --><bean?id="sqlSessionFactory"?class="org.mybatis.spring.SqlSessionFactoryBean"><property?name="dataSource"?ref="dataSource"?/>
        <!-- 將各Java類(lèi)的簡(jiǎn)寫(xiě)別名單獨(dú)放到文件mybatis.xml中,方便修改和管理?--><property?name="configLocation"?value="classpath:xml/mybatis.xml"?/>
    ? ?? <property?name="mapperLocations"?value="classpath:sql/*.xml"?/></bean> <!-- mybatis.xml文件 --><configuration><typeAliases><typeAlias alias="EntityA" type="com.xxxx.model.EntityA" /><typeAlias alias="EntityB" type="com.xxxx.model.EntityB" /><typeAlias alias="EntityC" type="com.xxxx.model.EntityC" /><typeAlias alias="User" type="com.xxxx.model.User" /></typeAliases></configuration>

    ?

    2. foreach標(biāo)簽的使用

    如果查詢接口只有一個(gè)參數(shù),參數(shù)類(lèi)型為list,則標(biāo)簽中的collection屬性應(yīng)該設(shè)定collection="list";參數(shù)類(lèi)型為數(shù)組,則應(yīng)設(shè)定為collection="array"。 如果查詢接口有多個(gè)參數(shù),則最好通過(guò)Map來(lái)傳遞各參數(shù)。此時(shí),foreach標(biāo)簽的collection屬性應(yīng)設(shè)置為,Map中表示集合參數(shù)的鍵。 如上面的代碼中,表示集合參數(shù)是eventIds,它在Map中的鍵為"eventIds"?,所以collection="eventIds"。

    處理時(shí)間對(duì)比

    各表數(shù)據(jù)量在200、300條左右,List<UserEvent>集合記錄為13條。 雖然優(yōu)化后的代碼行數(shù)有所增加,查詢結(jié)果解析略微復(fù)雜,但是十幾條數(shù)據(jù)的查詢已有2秒的差距。

    ?

    http://www.cnblogs.com/quiet-snowy-day/p/6166340.html

    ?

    總結(jié)

    以上是生活随笔為你收集整理的Mybatis中的collection、association来处理结果映射的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。