[Mybatis] HashMap #{} SQL Syntax에러 처리

문제 발생

  • 실습 과제중에 사원들을 월급별로 정렬 할 때 desc / asc 값을 Hashmap형태로 보내주었는데 내가 생각한대로 짰을 때 SQL 쿼리 에러 발생 했음

코드 과정

  • Servlet에서 order값을 String에 담은뒤 service에는 String으로 일단 넘겨줌
  • service에서 order를 HashMap<String, String> = ("order", order) 형태로 묶어서 dao로 넘김
  • dao에서 mapper에 map으로 parameter넘겨 줬음
  • mapper에서 sql문을
<select id = "order" resultType="EmpDTO" parameterType="HashMap">
    select empno, ename, job, mgr, to_char(hiredate, 'YYYY-MM-DD') hiredate, sal,    comm, deptno
    from emp 
    order by sal #{order}
</select>

이런식으로 짰는데 오류 생겼음, 요인은 order값을 asc나 desc로 인식을 못한것 같음

해결책

  • 첫번째로 알게된 점은 #{param} 형태로 처리하면 String 타입일 경우 자동으로 ' ' 처리가 된다는 것이었다.
  • 즉, 내가 예상하는 order by sal desc가 아닌 order by sal 'desc'의 형태가 되기 때문에 오류가 발생하는 것이었다.
  • 그렇기 때문에 만약 내가 원하는대로 출력을 하고 싶으면 #{}가 아닌 ${}를 사용해야한다.(#{}와 ${}의 차이는 추후 포스팅 할것이다.)
  • 만약 map의 형태로 안전하게 출력을 하고 싶다면
<select id = "order" resultType="EmpDTO" parameterType="HashMap">
    select empno, ename, job, mgr, to_char(hiredate, 'YYYY-MM-DD') hiredate, sal, comm, deptno
    from emp 

    <if test = "order == 'desc'">
        order by sal desc
    </if>
    <if test = "order == 'asc'">
        order by sal asc
    </if>

    </select>
  • test에 key를 넘겨주면 value값을 비교하기때문에 동적 할당을 통해 비교하게 되면 성공적으로 출력이 된다.

번외

  • 해결방법중 ${}를 사용하는 것과 map이 아닌 애초에 String으로 넘기는 경우를 해보았음
  • ${}를 사용할 경우 hashmap으로 넘겨주는 형태는 유지하면서 mapper에서 감싸주는 형태만 변환
<select id = "order" resultType="EmpDTO" parameterType="HashMap">
    select empno, ename, job, mgr, to_char(hiredate, 'YYYY-MM-DD') hiredate, sal, comm, deptno
    from emp 
    order by sal ${order1}


    </select>
  • map에다가 데이터를 ("order1", order)형태로 저장했음 key, value넘겨주는게 헷갈려서..
  • 아무튼 이렇게하면 성공적으로 실행이 된다.
  • ${}의 경우 parameter를 변환없이 그대로 넘겨주는 것이기 때문에 SQL injection문제에 취약하기 때문에 order by와 같은 경우를 제외하고 #{}를 쓴다고 한다.
  • 그것마저 불안하다면 #{}를 쓰는게 맞을듯?
  • String으로 넘겨주는 경우도 if동적 할당을 해주거나 ${}을 통해 작업한다면 처리 가능할듯

'skill > Mybatis' 카테고리의 다른 글

[Mybatis] 동적쿼리 foreach 사용해서 delete  (0) 2021.04.08

+ Recent posts