IT/development

[mybatis] mybatis 동적쿼리(feat. <where></where>)

알 수 없는 사용자 2022. 11. 20.

mybatis Dynamic SQL 😃

계속 실수 했던 동적쿼리이다.

오늘 나는 이걸 이해 했지만 미래의 넌 또 까먹을 수 있으니 여기에 메모해 둔다.

동적 WHERE

회원 테이블에서 회원이름과 이메일의 존재에 따라 동적으로 WHERE을 붙여서 검색하는 예시이다.

기존에는 mapper xml에서 아래처럼 작성했었다. 

쿼리를 작성하고는 반드시 단위 테스트를 여러번 해봐야 한다는 걸 또 깨달았다.(그걸 이제 알았니? 😥)

<select id="findMembersByCondition" parameterType="com.example.devlsyservice1.domain.dto.MemberDto" resultMap="memberMap">
        SELECT * FROM member
        <if test="memberName != null and memberName != ''" >
            WHERE member_name = #{memberName}
        </if>
        <if test="email != null and email != ''">
            WHERE email = #{email}
        </if>

역시 개발하면서 JUnit으로 단위 테스트를 계속 해야 한다.

이걸 모르고 나중에 tomcat을 띄웠다면 에러를 너무 늦게 발견 하게 될 것이다.

단위 테스트 결과 memberName과 email을 parameter로 1개씩만 넘기면 아래처럼 잘 작동한다.

그래서 난 그냥 잘된다고 생각하고 넘어 갔었다.

하지만 개발자는 다양한 테스트 케이스를 염두해 두고 개발을 해야 한다.

사용자는 절대 내가 설계한 대로만 사용하지 않는다.

만일 위 쿼리에서 어떤 사용자가 회원과 이메일을 동시에 조건으로 검색하면? 잘 될까?

결과적으로 WHERE절이 2번 나오게 되는 문법 오류가 발생한다.(잘못 작성한 경우다.)

아래처럼 쿼리를 변경해야 한다.

SELECT * FROM member
        <where>
            <if test="memberName != null and memberName != ''" >member_name = #{memberName}</if>
            <if test="email != null and email != ''">AND email = #{email}</if>
        </where>

이제 다시 테스트 해보면 제대로 된 쿼리가 실행된다.

물론 조건을 하나씩만 줘도 잘 작동한다.

<where>태그안에 조건 중 한가지만 해당되면 WHERE절만 붙이고 해당 조건 실행,

만일 일치한 조건에 AND나 OR가 있을 경우 이를 지운다.(그래서 아래처럼 쿼리를 변경해도 잘 작동한다.)

SELECT * FROM member
        <where>
        	<!-- 조건이 1개인 경우면 일치한 조건의 AND가 지워져서 쿼리가 실행됨 --> 
            <if test="memberName != null and memberName != ''" >AND member_name = #{memberName}</if>
            <if test="email != null and email != ''">AND email = #{email}</if>
        </where>

결과는 아래처럼 첫번 째 조건의 AND가 지워져서 실행된다.

정리 

참조: https://mybatis.org/mybatis-3/ko/dynamic-sql.html

 

MyBatis – 마이바티스 3 | 동적 SQL

동적 SQL 마이바티스의 가장 강력한 기능 중 하나는 동적 SQL을 처리하는 방법이다. JDBC나 다른 유사한 프레임워크를 사용해본 경험이 있다면 동적으로 SQL 을 구성하는 것이 얼마나 힘든 작업인지

mybatis.org


개인 스터디 기록을 메모하는 공간이라 틀린점이 있을 수 있습니다.

틀린 점 있을 경우 댓글 부탁드립니다.

 

[mybatis] foreach parameterType hashmap 예제

미래의 나를 위해 기록한다. 😃mybatis에서 foreach를 돌릴 때 list는 이제 좀 익숙해 졌는데 map은 아직 좀 서툰 느낌이 들어 기록한다.예제는 동적으로 insert문의 내용과 SELECT문의 내용을 채우는 예

yaga.tistory.com

 

[mybatis] mybatis 배열 저장(feat. foreach)

목차 위와 같이 insert를 1개 이상 하는 로직을 만들게 되었고 미래의 내가 보기 위해 기록한다. 😄 클라이언트에서 배열로 값을 받아서 DB에 저장하는 기능이 필요했다. 참고로 mysql과 Oracle은 문

yaga.tistory.com

 

댓글