iBatis2.x 에서 3으로 오면서 바뀐 변화 중 하나가 바로 ParameterMap이 빠진 것이다.

iBatis3 에서 ParameterMap 을 사용하지 못하게 되면서 Mapper 클래스에 여러개의 파라미터를 전달하는 방법에도 변화가 생겼다. 이전에는 mapper 메소드에 전달되는 파라미터 양식에 맞춰서 ParameterMap을 정의하거나, HashMap 객체를 파라미터로 전달해서 dynamic query 를 구성하는 방식을 사용했었다.

양쪽 방식의 차이점은 parameter map 을 조립하는 시점인데, 전자의 경우는 xml 설정 파일을 읽어서 미리 parameter map을 조립하지만 hashmap 을 전달할때에는 런타임 시점에 hashmap을 까봐서 그 안에 들어있는 인스턴스들을 보고 parameter map을 조립한다.

iBatis3 에서 parameterMap에 대한 지원을 안하면서 사실상 parameter map은 실행 시점에 조립되는 듯 하다.(자세한 구현 내용은 확인을 못했지만 파라미터로 뭐가 들어올지 모른다면 미리 parameter map을 만들어 놓는게 불가능하지 않을까?)

예를 들자면 다음과 같은 경우를 말한다.
위에서는 두 개의 파라미터만 전달받지만 dynamic 쿼리를 만들때 여러개의 파라미터가 필요하다면 3~4개 이상이 전달되는 경우도 없지는 않다.

1. @Param annotation 이용방법

iBATIS 3 에서 새로 도입된 @Param 어노테이션을 적용해서 다음과 같이 Mapper 인터페이스를 선언한다.
저렇게 여러개의 파라미터에 참조될 이름을 적어주면 iBatis 안에서파라미터들을 처리하는 방식은 아래와 같다.

우선 파라미터들을 모아서 다음과 같이 map 객체를 만든다.

그리고 조립된 맵 객체를 쿼리의 parameter로 전달하고 실제 sql 에서는 다음과 같이 참조한다.
<select id="selectUsersBetweenAges" resultType="project.bean.User">
SELECT
    user_id as "id"
    , user_name as "userName"
    , ...
    ..
FROM Users
WHERE user_age BETWEEN #{age0} AND #{age1}
</select>

2. Annotation을 쓰지 않는 방법.

annotation 방식을 쓰지 않고도 쿼리에서 #{0}, #{1}과 같이 파라미터를 참조할 수 있다. 0, 1, 2와 같은 숫자는 파라미터가 메소드에 전달된 순서를 나타내는데 @Param("..") 으로 참조할 파라미터의 이름을 써주지 않을 경우 다음과 같이 위치를 key값으로 등록한다.
이제 sql 에서는 다음과 같이 참조한다.
<select id="selectUsersBetweenAges" resultType="project.bean.Customer">
SELECT
    c.cust_id as "id"
    , c.cust_name as "customerName"
    , ...
    ..
FROM Customers c, Phones phone
WHERE c.cust_id = phone.owner_id
    AND phone.number1 LIKE #{1}
    AND c.first_name LIKE #{0}
</select>
#{0}은 첫번째 파라미터인 name을, #{1}은 두번째 파라미터인 전화번호를 나타낸다.

그런데 이렇게 전달된 파라미터가 dynamic 쿼리 안에서 쓰일때는 참조 방식을 #{1} 이 아니라 [1] 과 같이 해야 한다.

        <if test="[1] == true"> c.first_name = #{0}</if>
        <if test="[1] != true">  c.first_name LIKE #{0} </if>

annotation을 쓰든 안쓰든 여러개의 파라미터가 map 인스턴스로 전달되기 때문에 실제 동작에는 별 차이가 없으나 annotation을 쓰지 않았을때 #{0}, #{1} 과 같은 숫자를 보고 무슨 값인지 알기가 어렵기 때문에 가독성이 떨어진다.

따라서 별다른 제약이 없다면 annotation을 사용하는게 더 나을 듯 싶다.




Posted by yeori
,