목차

parameterMap

parameterMap 은 해당 요소로 SQL 문 외부에 정의한 입력 객체의 속성에 대한 name 및 javaType, jdbcType 을 비롯한 옵션을 설정할 수 있는 매핑 요소이다. 이를 통해 JavaBeans 객체(또는 Map 등)에 대한 prepared statement 에 대한 바인드 변수 매핑을 처리할 수 있다. 유사한 기능을 처리하는 parameterClass 나 Inline Parameter 에 비해 많이 사용되지 않지만 더 기술적인(descriptive) parameterMap(예를 들어 stored procedure 를 위한) 이 필요하거나, XML 의 일관된 사용과 순수성을 지키고자 할때 좋은 접근법이 될 수도 있다. 그러나 Dynamic 요소와 함께 사용될 수 없고 바인드 변수의 갯수와 순서를 정확히 맞춰야 하는 불편이 있는 등 일반적으로 사용을 추천하지 않는다.

기본 parameterMap 사용 방법

아래의 샘플 parameterMap 정의를 참고하라.

Sample parameterMap

	..
	<typeAlias alias="empVO" type="egovframework.rte.psl.dataaccess.vo.EmpVO" />
 
	<parameterMap id="empParam" class="empVO">
		<parameter property="empNo" javaType="decimal" jdbcType="NUMERIC" />
		<parameter property="empName" javaType="string" jdbcType="VARCHAR" nullValue="blank" />
		<parameter property="job" javaType="string" jdbcType="VARCHAR" nullValue="" />
		<parameter property="mgr" javaType="decimal" jdbcType="NUMERIC" />
		<parameter property="hireDate" javaType="date" jdbcType="DATE" />
		<parameter property="sal" javaType="decimal" jdbcType="NUMERIC" />
		<parameter property="comm" javaType="decimal" jdbcType="NUMERIC" nullValue="-99999" />
		<parameter property="deptNo" javaType="decimal" jdbcType="NUMERIC" />
	</parameterMap>
 
	<insert id="insertEmpUsingParameterMap" parameterMap="empParam">
		<![CDATA[
			insert into EMP
			           (EMP_NO,
			            EMP_NAME,
			            JOB,
			            MGR,
			            HIRE_DATE,
			            SAL,
			            COMM,
			            DEPT_NO)
			values     (?,
			            ?,
			            ?,
			            ?,
			            ?,
			            ?,
			            ?,
			            ?)
		]]>
	</insert>

위 sql 매핑 파일에서 parameterMap 요소로 empParam 이라는 id 를 부여하고 대상 입력 객체는 EmpVO 를 지정하고 있다. EmpVO 에 대한 상세 attribute (속성) 들에 대해 parameter 하위 요소로 매핑 정의를 하고 있는데 이때 추가적으로 javaType, jdbcType 에 대해 위에서는 명시하였다. (java 의 reflection 기술을 사용하여 대상 클래스의 개별 속성에 대한 type 을 구하는 것보다 직접 type 에 대한 지시를 설정으로 명시하므로 약간의 성능상 이점이 있을 수 있다.) 위에서는 동일한 property 가 중복으로 사용되는 경우가 없으나 parameterMap 은 아래의 insertEmpUsingParameterMap mapped statement 예에서 보듯이 ? 에 대한 순서대로 매핑되므로 만약 중복으로 사용되는 경우가 필요하다면 parameterMap 정의부터 순서를 맞추어 동일한 property 의 중복 정의가 필요할 수 있다. 또한 nullValue 속성을 지정한 property 에 대해서는 해당 값이 nullValue 에 지정된 값으로 전달되는 경우 데이터베이스에는 null 로 처리가 이 외에도 typeName, resultMap, mode, typeHandler, numericScale 에 대한 속성 정의가 가능하다.

Sample TestCase

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath*:META-INF/spring/context-*.xml" })
@TransactionConfiguration(transactionManager = "txManager", defaultRollback = false)
@Transactional
public class ParameterMapTest extends TestBase {
 
    @Resource(name = "empDAO")
    EmpDAO empDAO;
 
    @Before
    public void onSetUp() throws Exception {
        // DB 초기화
    }
 
    public EmpVO makeVO() throws ParseException {
        EmpVO vo = new EmpVO();
        vo.setEmpNo(new BigDecimal(9000));
        vo.setEmpName("test Emp");
        vo.setJob("test Job");
 
        // 7839,'KING','PRESIDENT'
        vo.setMgr(new BigDecimal(7839));
        SimpleDateFormat sdf =
            new SimpleDateFormat("yyyy-MM-dd", java.util.Locale.getDefault());
        vo.setHireDate(sdf.parse("2009-02-09"));
        // mysql 5.0.X에서는 소숫점 자릿수 만큼 .00 이 달려 나와 테스트 편의상 소숫점 자리수가 없도록 칼럼 선언 하였음.
        if (isMysql) {
            vo.setSal(new BigDecimal("12345"));
            vo.setComm(new BigDecimal(100));
        } else {
            vo.setSal(new BigDecimal("12345.67"));
            vo.setComm(new BigDecimal(100.00));
        }
        // 10,'ACCOUNTING','NEW YORK'
        vo.setDeptNo(new BigDecimal(10));
        return vo;
    }
 
    public void checkResult(EmpVO vo, EmpVO resultVO) {
        assertNotNull(resultVO);
        assertEquals(vo.getEmpNo(), resultVO.getEmpNo());
        assertEquals(vo.getEmpName(), resultVO.getEmpName());
        assertEquals(vo.getJob(), resultVO.getJob());
        assertEquals(vo.getMgr(), resultVO.getMgr());
        assertEquals(vo.getHireDate(), resultVO.getHireDate());
        assertEquals(vo.getSal(), resultVO.getSal());
        assertEquals(vo.getComm(), resultVO.getComm());
        assertEquals(vo.getDeptNo(), resultVO.getDeptNo());
    }
 
    @Test
    public void testParameterMapInsert() throws Exception {
        EmpVO vo = makeVO();
 
        // insert
        empDAO.insertEmp("insertEmpUsingParameterMap", vo);
 
        // select
        EmpVO resultVO = empDAO.selectEmp("selectEmp", vo);
 
        // check
        checkResult(vo, resultVO);
    }
 
    @Test
    public void testParameterMapInsertWithNullValue() throws Exception {
        EmpVO vo = new EmpVO();
        // key 설정
        vo.setEmpNo(new BigDecimal(9000));
 
        // parameterMap nullValue test
        vo.setEmpName("blank");
        vo.setJob("");
        // cf.) -99999.99 는 NumberFormatException 임을
        // 확인하였음!
        vo.setComm(new BigDecimal("-99999"));
 
        // insert
        empDAO.insertEmp("insertEmpUsingParameterMap", vo);
 
        // select
        EmpVO resultVO = empDAO.selectEmp("selectEmp", vo);
 
        // check
        assertNotNull(resultVO);
        assertEquals(vo.getEmpNo(), resultVO.getEmpNo());
        // parameterMap 설정에서 nullValue="blank" .. 에 따라
        // 해당값이 null 로 입력되었을 것임
        assertNull(resultVO.getEmpName());
        assertNull(resultVO.getJob());
        assertNull(resultVO.getComm());
    }
 
}

위에서 parameterMap 을 이용한 파라메터 객체 바인딩을 처리하는 insertEmpUsingParameterMap 쿼리문에 대해 입력객체를 세팅 후 입력/조회 처리하고 있는 테스트 케이스이다. 실제로 매핑 파일 내에서 parameterMap 을 사용하는 경우와 Inline parameter 또는 parameterClass 를 그대로 쓰는 경우에서도 어플리케이션 영역은 동일한 형태의 입력 객체를 인자로 iBATIS API 를 호출하게 된다. 위의 testParameterMapInsertWithNullValue 테스트 메서드에서는 parameterMap 에 nullValue 속성으로 지정한 특정한 값을 세팅 하므로써 DB 에 null 로 입력이 된 결과를 조회하여 assertNull 로 확인하고 있다.