1. 程式人生 > 實用技巧 >MyBatis使用collection標籤進行多層級巢狀查詢

MyBatis使用collection標籤進行多層級巢狀查詢

1.首先了解一下需求

目標是寫一個介面,活動碼錶查詢介面。

先看一下表結構和表資料。

要執行的操作是層級結構查詢,通過活動分類(activity_type)查詢所有活動名稱(activity_name),再通過所有活動名稱(activity_name)查詢所有活動一級名稱(activity_level1_name)及(activity_level1_code)。

至此結束。

2.思路(先說一下我第一次的思路)

首先,查出所有的活動分類並存儲在一個List<String>陣列中。

然後通過迴圈遍歷這個陣列,查出所有活動名稱並存儲在一個List<String>陣列中。

再通過遍歷這個陣列,查出所有活動一級名稱並存儲在一個List<String>陣列中。

然後在每個迴圈內進行資料的組裝。

比如:map.put("activityName", typeList.get(i));

map.put("child", firstNameList);

等等。。。。。。最後經過我不懈的努力,終於把資料格式組裝好了,開心了半天把介面提上去了,本以為前端同學能夠正常使用。。。結果。。。

3.問題出現

前端同學反饋,程式碼響應時間過長,無法使用,需要後端進行介面的優化。

當時使用PostMan測介面的時候確實發現了這個問題,但是當時對這個問題並不敏感,下次一定要注意。

我們再次使用PostMan進行測試,檢視請求時間。

真不錯,12.87秒,估計客戶可以抓一把瓜子邊磕邊等了。。。。。。

為什麼會慢?(小白,努力ing)

看一下程式碼。

    @Override
    public List<Map> queryListNew() {

        List<String> list = jfMarketingActivityMapper.queryActivityTypeList();

        List<Map<String, Object>> activityNameList = new
ArrayList<>(); List title = new ArrayList(); Map<String, Object> mapType; Map<String, Object> mapName; Map<String, Object> nameCode; List codeList; for (int i = 0 ; i < list.size() ; i++) { List<String> typeList = jfMarketingActivityMapper.typeList(list.get(i)); for (int j = 0 ; j < typeList.size() ; j++) { List<String> firstNameList = jfMarketingActivityMapper.firstNameList(typeList.get(j)); mapName = new HashMap<>(); mapName.put("activityName", typeList.get(j)); codeList = new ArrayList(); for (int k = 0 ; k < firstNameList.size() ; k++) { String code = jfMarketingActivityMapper.firstName(firstNameList.get(k)); nameCode = new HashMap<>(); nameCode.put("activityLevel1Code", code); nameCode.put("activityName", code + "_" + firstNameList.get(k)); codeList.add(k, nameCode); } mapName.put("child", codeList); activityNameList.add(j, mapName); } mapType = new HashMap<>(); mapType.put("activityName", list.get(i)); mapType.put("child", activityNameList); activityNameList = new ArrayList<>(); title.add(i, mapType); } return title; }

可以看到,在三層迴圈中,我們不斷的呼叫Mapper層進行sql的查詢操作。每次查詢都需要時間,三層迴圈之下導致時間過長。

所以我們要儘量減少sql的查詢操作。

4.collection標籤

之前做過的一個模組中,使用到了MyBatis的collection標籤。當時是需要給前端返回一個樹級的結構,一個層級關係。

於是我就想到應該可以直接在sql中把層級結構摟出來,這樣就大大減少了介面的響應時間。

不太一樣的地方就是這個層級是三級,可能需要巢狀使用collection標籤。

ServiceImpl層:

List<String> typeList = jfMarketingActivityMapper.queryActivityTypeList();

List<Map> allData = jfMarketingActivityMapper.allList(typeList);

for (int i = 0 ; i < allData.size() ; i++) {
List list = (List) allData.get(i).get("child");
for (int j = 0 ; j < list.size() ; j++) {
Map<String, Object> map = (Map<String, Object>) list.get(j);
List list1 = (List) map.get("child");
for (int k = 0 ; k < list1.size() ; k++) {
Map<String, Object> map1 = (Map<String, Object>) list1.get(k);
map1.put("activityName", map1.get("activityLevel1Code") + "_" + map1.get("activityName"));
}
}
}

return allData;

}

Mapper層:

List<Map> allList(@Param("typeList") List<String> typeList);

MyBatis層:

    <resultMap id="child" type="java.util.Map">
        <result property="activityName" column="activity_name"/>
        <collection property="child" ofType="java.util.Map" javaType="ArrayList" resultMap="child2">
        </collection>
    </resultMap>

    <resultMap id="child2" type="java.util.Map">
        <result property="activityName" column="activity_level1_name"/>
        <result property="activityLevel1Code" column="activity_level1_code"/>
    </resultMap>

    <resultMap id="list" type="java.util.Map">
        <result property="activityName" column="activity_type"/>
        <collection property="child" ofType="java.util.Map" javaType="ArrayList" resultMap="child">
        </collection>
    </resultMap>

    <select id="allList" resultMap="list">
        SELECT activity_type, activity_name, activity_level1_name, activity_level1_code
        FROM jf_marketing_activity
        WHERE 1=1 AND activity_type IN
        <foreach collection="typeList" item="list" index="index" open="(" separator="," close=")">
            #{list}
        </foreach>

    </select>

程式碼實現,通過MyBatis層使用collection標籤進行多層級巢狀查詢,實現類中的迴圈是前端要求拼接code所以進行迴圈。

可以看到介面響應時間變成96ms,12.87s和96ms,一百三十多倍。。。。。。

5.總結

下次寫程式碼的時候不光要只考慮能實現,還要考慮一些效能方面的問題。