들어가며

현재 투입되어있는 프로젝트의 서비스 중에는 특정 데이터를 조회할 수 있는 화면이 있습니다.

그런데 이 화면을 사용하게되는 업무 특성상 데이터를 일일이 하나씩 조회하기가 번거롭다는 불편사항이있어

이를 한번에 다중 검색 가능하도록 수정 조치하였고, 당시 작업내용을 핵심부분만 간략하게 정리하였습니다.

기존 방식

  • mapper.xml
<sql id="ticketSearch">
    <if test="(method_info != null and method_info != '')">
        <if test="method_id == 'gkId'">
            AND GK_ID = #{method_info}
        </if>
        <if test="method_id == 'parentTicketId'">
            AND UPPER(PRNT_TKT_ID) LIKE CONCAT('%',UPPER(REPLACE(#{method_info}, '_', '#_')),'%') ESCAPE '#'
        </if>
        <if test="method_id == 'ticketId'">
            AND UPPER(TKT_ID) LIKE CONCAT('%',UPPER(REPLACE(#{method_info}, '_', '#_')),'%') ESCAPE '#'
        </if>
        <if test="method_id == 'guid'">
            AND GUID LIKE CONCAT('%',#{method_info},'%')
        </if>
    </if>
</sql>

<select id="list" parameterType="map" resultMap="ticketVO">
    SELECT
        컬럼 1,
        컬럼 2,
        컬럼 3
    FROM
        테이블 A
    WHERE
        DEL_YN_FG = 'N' 
        <include refid="ticketSearch"/>
</select>

▲ 화면에서 입력한 문자열 1개를 포함하고있는 데이터를 “like” 검색을 통한 단일 조회 방식

작업 내용

  1. 검색하고자하는 데이터의 종류가 "gkId", "parentTicketId", "ticketId" 중 하나일 경우, 화면에서 검색어 입력 시 구분자(콤마(”,”) 혹은 공백(” ”))를 기준으로 각각의 검색어를 “포함”하는 데이터를 전체 조회하도록 수정

  2. MyBatis foreach > “separator"를 활용한 OR 조건 동적 쿼리 적용

service.java (로직 추가)

protected void setMultipleSearchInfo(Map<String, Object> reqMap){
    String method_info = GkUtils.nvl(reqMap, METHOD_INFO);
    String method_id = GkUtils.nvl(reqMap, METHOD_ID);

    if( !(Arrays.asList("gkId", "parentTicketId", "ticketId").contains(method_id))
            && StringUtil.isEmpty(method_info)) return;

    method_info = method_info.replaceAll("\\s{2,}", " ").trim();
    String[] splitStr = method_info.split("[\\s,]+");

    if("gkId".equals(method_id)){
        splitStr = Arrays.stream(splitStr)
                .map(str -> GkUtils.getPlainGkId(str))
                .toArray(String[]::new);
    }
    reqMap.put("method_info_list", splitStr);
}
  • 특정 카테고리 여부 체크

  • 구분자 기준으로 split → String[] 타입 파라미터에 Set

mapper.xml (MyBatis 동적 쿼리 적용)

<sql id="ticketSearch">
    <if test="(method_info != null and method_info != '')">
        <if test="method_id == 'gkId'">
            <choose>
                <when test="method_info_list != null and method_info_list.length > 1">
                    AND
                    <foreach collection="method_info_list" item="item" open="(" close=")" separator="OR">
                        GK_ID LIKE CONCAT('%', REPLACE(#{item}, '_', '#_'), '%') ESCAPE '#'
                    </foreach>
                </when>
                <otherwise>
                    AND GK_ID = #{method_info}
                </otherwise>
            </choose>
        </if>
        <if test="method_id == 'parentTicketId'">
            <choose>
                <when test="method_info_list != null and method_info_list.length > 1">
                    AND
                    <foreach collection="method_info_list" item="item" open="(" close=")" separator="OR">
                        PRNT_TKT_ID LIKE CONCAT('%', REPLACE(#{item}, '_', '#_'), '%') ESCAPE '#'
                    </foreach>
                </when>
                <otherwise>
                    AND PRNT_TKT_ID LIKE CONCAT('%',REPLACE(#{method_info}, '_', '#_'),'%') ESCAPE '#'
                </otherwise>
            </choose>
        </if>
        <if test="method_id == 'ticketId'">
            <choose>
                <when test="method_info_list != null and method_info_list.length > 1">
                    AND
                    <foreach collection="method_info_list" item="item" open="(" close=")" separator="OR">
                        TKT_ID LIKE CONCAT('%', REPLACE(#{item}, '_', '#_'), '%') ESCAPE '#'
                    </foreach>
                </when>
                <otherwise>
                    AND TKT_ID LIKE CONCAT('%',REPLACE(#{method_info}, '_', '#_'),'%') ESCAPE '#'
                </otherwise>
            </choose>
        </if>
        <if test="method_id == 'guid'">
            AND GUID LIKE CONCAT('%',#{method_info},'%')
        </if>
    </if>
</sql>

<select id="list" parameterType="map" resultMap="ticketVO">
    SELECT
        컬럼 1,
        컬럼 2,
        컬럼 3
    FROM
        테이블 A
    WHERE
        DEL_YN_FG = 'N' 
        <include refid="ticketSearch"/>
</select>