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.總結

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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM