1. Where 1=1
▶ WHERE 1 = 1 을 사용했던 이유
- 동적 쿼리에서 WHERE절 최상단에 1 = 1 을 적어 놓으면
Mybatis의 If문 작성도 편하게 AND로 처리할 수 있고, 주석 처리또한 쉬워진다.
▶ WHERE 1 = 1 의 위험성
- SELECT문에서는 심각한 문제까지는 아니지만 문제가 발생한다.
<select id="selectUser" resultType="kr.test.dto.user.userInfo">
SELECT id, name
FROM db_user.dbo.tbl_user
WHERE 1=1
<if test="userid != null and userid != ''">
AND userid = #{userid}
</if>
</select>
위 쿼리에서 userid가 없을 경우, 전체 회원이 조회되는 이슈가 발생한다.
- UPDATE, DELETE문에서는 심각한 문제 발생이 야기된다.
<update id="updatetUser">
UPDATE db_user.dbo.tbl_user
SET user_alias = #{user_alias}
WHERE 1=1
<if test="userid != null and userid != ''">
AND userid = #{userid}
</if>
</update>
위 쿼리에서는 userid가 없을 경우, 전체 회원의 별명이 업데이트되는 심각한 문제가 발생된다.
2. where 태그
▶ WHERE 1 = 1 의 대체 where 태그
- where 태그가 맨 첫 조건의 AND는 자동으로 제외시켜 준다.
<update id="updatetUser">
UPDATE db_user.dbo.tbl_user
SET user_alias = #{user_alias}
WHERE
<where>
<if test="userid != null and userid != ''">
AND userid = #{userid}
</if>
</where>
</update>
하지만 이 쿼리 또한 userid가 없다면 전체 회원의 별명을 업데이트 시킨다.
3. trim 태그
▶ WHERE 1 = 1 의 대체 trim 태그 (정답)
- prefix="WHERE "이 있는 경우
<update id="updatetUser">
UPDATE db_user.dbo.tbl_user
SET user_alias = #{user_alias}
<trim prefix="WHERE" prefixOverrides="AND">
<if test="userid != null and userid != ''">
AND userid = #{userid}
</if>
</trim>
</update>
위 쿼리 또한 userid가 없다면 WHERE절 자체가 없는것으로 인식되어 전체 회원이 업데이트 된다.
- prefix="WHERE "을 제거한 경우
<update id="updatetUser">
UPDATE db_user.dbo.tbl_user
SET user_alias = #{user_alias}
WHERE
<trim prefixOverrides="AND">
<if test="userid != null and userid != ''">
AND userid = #{userid}
</if>
</trim>
</update>
그디어 전체 회원 업데이트 이슈를 해결하였다.
위 쿼리에서 userid가 없다면 BadSqlGrammarException이 발생하면서 예외 처리된다.
4. 끝
▶ 안전한 쿼리를 위한 유효성 검증
- 쿼리에서 trim태그 사용은 마지막 보루의 개념으로 생각하고 예외 발생을 막는것이 더 좋은 프로그램이 될 것 이다.
- DTO에서 valid 옵션으로 체크하는 방법을 추천한다.