1. 程式人生 > >mybatis 動態sql語句實現多條件查詢(foreach的使用)

mybatis 動態sql語句實現多條件查詢(foreach的使用)

一、前言

現有一個需求:實現多條件、不確定條件的搜尋功能。

類似於淘寶網進行搜尋商品的時候,可以在搜尋框進行模糊搜尋,同時可以進行條件篩選,例如想買一隻 口紅? 的時候,可以在搜尋框內輸入“口紅”,還可以選擇品牌、否包郵、價格區間等等。。最後搜尋出來的結果是滿足所有篩選的條件的。

這裡我認為的難點就是:這些條件你不確定需不需要,你不確定選了幾個,所以說這些都動態的。

我總結了一句話來進行概括:同類型條件取並集,不同型別條件取交集

二、前臺介面(瞭解需求)

頁面預設載入全部資料
當有搜尋條件後,取滿足所有條件的資料:試題內容中包括關鍵字”程式“、試題型別為”判斷題“、所屬知識點為”關係運算符、物件的概念“。 這裡前臺使用了easyui框架、下拉框多選技術、easyUI分頁技術參考我的這兩篇博文:

在本頁面可以看出,在所有試卷中,可以通過關鍵字搜尋試題內容,通過複選下拉框篩選”試題型別“、”所屬知識點“這兩種條件。

三、mybatis sql語句

這個sql涉及到了三張表的查詢,其中還包括巢狀查詢。寫這個之前真的沒想到自己能寫出這麼複雜的sql語句。 暫時還沒考察其健壯性,現在就是把功能都實現了。 把sql語句貼出來:
<select id="selectAllQuestions" resultType="java.util.Map">
        SELECT <include refid="Extend_Column_List"/>, kp.kp_title as kp_value, sys.code_text as question_type_value
        FROM aim_test_questions qt
        inner join amc_knowledgepoint_base_t kp
        on qt.belong_kpcode = kp.kp_code and qt.question_state = '1'
        inner join sys_code_t sys
        on sys.code_data = qt.question_type and sys.code_kind_1 = '試題型別'
        <where>
            <if test="question_content != null and question_content != ''">
                and question_content LIKE CONCAT(CONCAT('%',#{question_content}),'%')
            </if>
            <if test="kp_title!=null and kp_title.size!=0">
                and qt.belong_kpcode in (
                SELECT kp.kp_code
                FROM amc_knowledgepoint_base_t kp
                <where>
                    kp.kp_title in
                    <foreach collection="kp_title" index="index" item="item" open="(" separator="," close=")">
                    #{item}
                    </foreach>
                </where>
                )
            </if>
            <if test="code_text!=null and code_text.size!=0">
                and qt.question_type in (
                SELECT sys.code_data
                FROM sys_code_t sys
                <where>
                    sys.code_text in
                    <foreach collection="code_text" index="index" item="item" open="(" separator="," close=")">
                    #{item}
                    </foreach>
                </where>
                )
            </if>
        </where>
        order by qt.question_create_time asc
 </select>
where前面的不用看,主要看<where>裡面有三個<if>。這就是”不同型別條件取交集“,所以這裡用到了 <where> <if>  </if>  <if> </if> <if> </if> </where>這樣的結構來對條件進行篩選。 第一個<if>實現了關鍵字的模糊搜尋。 第二個<if>由於涉及到了另一張表的條件查詢,所以用到了巢狀查詢。 在前臺,下拉框的條件值可以為多個。所以前臺會給後臺傳一個list,其中 kp_title 是用來存放第一個下拉框的值的一個Map。 在這個巢狀語句裡面用到了<foreach></foreach>,可以對map、list、array這三種資料型別進行遍歷。在本栗子中,
<foreach collection="kp_title" index="index" item="item" open="(" separator="," close=")">
    #{item}
</foreach>
collection裡面的kp_title為map的key值。item是用來遍歷map的value值的一個別名。 第三個<if>與第二個的內容相似,只不過是又多關聯查詢了第三張表。

四、總結

當時寫這個sql語句真可謂是”吭哧癟肚“呀,哈哈。其實現在想想也不難。重要的是要把需求先捋清楚。 然後mybatis的sql語句不要著急直接往裡面寫。可以先在資料庫裡面把sql語句敲一遍,確認無誤後,再寫mybatis。 遇到像上面這種需求比較多的,可以把需求拆分。例如先把一個模糊搜尋的功能實現。然後再實現其他的功能。 感覺當時寫這個的時候有點費勁,所以想貼出來給大家分享,如果不對的地方希望各位大牛能多多指正,大家一起交流一起進步。