이전에 살펴본 prepared statement 에 대한 바인드 변수 매핑 처리를 위한 parameterMap 요소(SQL 문 외부에 정의한 입력 객체 property name 및 javaType, jdbcType 을 비롯한 옵션을 설정매핑 요소) 와 동일한 기능을 처리하는 간편한 방법을 Inline Parameters 방법으로 제공한다. 보통 parameterClass 로 명시된 입력 객체에 대해 바인드 변수 영역을 간단한 #property# 노테이션으로 나타내는 Inline Parameter 방법은 기존 parameterMap 에서의 ? 와 이의 순서를 맞춘 외부 parameterMap 선언으로 처리하는 방법에 비해 많이 사용되고 일반적으로 추천하는 방법이다. 이는 Dynamic 요소와 함께 사용될 수 있고 별도의 외부 매핑 정의없이 바인드 변수 처리가 필요한 위치에 해당 property 를 직접 사용 가능하며, 필요한 경우 jdbcType 이나 nullValue 를 간단한 추가 노테이션(ex. #empName:VARCHAR:blank# ) 와 같이 지정할 수 있고, 상세한 옵션이 필요한 경우에는 (ex. #comm,javaType=decimal,jdbcType=NUMERIC,nullValue=-99999# ) 와 같이 ,(comma) 로 구분된 필요한 속성=값 을 상세하게 기술할 수도 있다.
아래의 샘플 Inline Parameters 사용 쿼리문을 참고하라.
.. <typeAlias alias="empVO" type="egovframework.rte.psl.dataaccess.vo.EmpVO" /> <insert id="insertEmptUsingInLineParam"> <![CDATA[ insert into EMP (EMP_NO, EMP_NAME, JOB, MGR, HIRE_DATE, SAL, COMM, DEPT_NO) values (#empNo:NUMERIC#, #empName:VARCHAR:blank#, #job:VARCHAR:""#, /* inline parameter 에서는 empty String 을 nullValue로 대체할 수 없음 - cf.) oracle인 경우는 "" 가 null 임 */ #mgr:NUMERIC#, #hireDate:DATE#, #sal:NUMERIC#, #comm,javaType=decimal,jdbcType=NUMERIC,nullValue=-99999#, #deptNo:NUMERIC#) ]]> </insert>
위 sql 매핑 파일에서 별도의 parameterMap 외부 정의없이 #property:jdbcType# 형태로 직접 바인드 변수 영역에 나타내고 있다. #property# 만 나타내어도 iBATIS 에서 자동으로 타입처리는 잘된다. 위에서는 해당 쿼리에 parameterClass=“empVO” 에 대한 입력 객체 설정이 나타나 있지 않음에도 iBATIS 에서 런타임에 인자로 주어지는 입력 객체를 자동으로 파악하여 파라메터 처리를 하고 있음을 확인할 수 있다. 그러나 parameterClass 의 명시는 성능 상 반드시 추천하는 바이다.
이 외에도 속성=값 형태의 옵션 설정을 , 를 구분자로 아래와 같이 나타낼 수 있다.
위에서 ? 부분을 해당 속성에 따라 적절한 값으로 설정하면 된다. mode 는 stored procedure 의 IN/OUT/INOUT 모드를 지시할 수 있는 속성이고 numericScale 은 stored procedure 의 OUT/INOUT 변수가 decimal 이나 numeric인 경우 DBMS 의 Scale 정보를 유지하기 위해 명시해야 하는 속성이다. handler 속성에는 typeHandler 를 지시할 수 있다.
.. 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 은 소숫점 이하 자리가 .00 으로 기본 들어가게 되어 테스트 편의상 numeric(5) 로 선언하였음. 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 testInLineParameterInsert() throws Exception { EmpVO vo = makeVO(); // insert empDAO.insertEmp("insertEmptUsingInLineParam", vo); // select EmpVO resultVO = empDAO.selectEmp("selectEmp", vo); // check checkResult(vo, resultVO); } @Test public void testInLineParameterInsertWithNullValue() throws Exception { EmpVO vo = new EmpVO(); // key 설정 vo.setEmpNo(new BigDecimal(9000)); // inline parameter nullValue test vo.setEmpName("blank"); // inline parameter 에서는 empty String 을 // nullValue로 대체할 수 없음 // ref.) // http://www.nabble.com/inline-map-format%3A-empty-String-in-nullValue-td18905940.html vo.setJob(""); // cf.) oracle 인 경우 "" 는 null 과 // 같음! vo.setComm(new BigDecimal("-99999")); // insert empDAO.insertEmp("insertEmptUsingInLineParam", vo); // select EmpVO resultVO = empDAO.selectEmp("selectEmp", vo); // check assertNotNull(resultVO); assertEquals(vo.getEmpNo(), resultVO.getEmpNo()); // inline parameter 설정에서 // #empName:VARCHAR:blank# .. // 에 따라 해당값이 null 로 // 입력되었을 것임 assertNull(resultVO.getEmpName()); // inline parameter 에서는 empty String 을 // nullValue로 대체할 수 없음 확인! // cf.) parameterMap 케이스에서는 // assertNull(resultVO.getJob()) // cf.) oracle // 인 경우 "" 는 null 과 같음! // assertNotNull(resultVO.getJob()); assertNull(resultVO.getComm()); } ..
위에서 Inline Parameters 을 이용한 파라메터 객체 바인딩을 처리하는 insertEmptUsingInLineParam 쿼리문에 대해 입력객체를 세팅 후 입력/조회 처리하고 있는 테스트 케이스이다. 실제로 위 어플리케이션 영역은 parameterMap 사용 시와 차이가 없음을 알 수 있다. 위의 testInLineParameterInsertWithNullValue 테스트 메서드에서는 Inline Parameters 에 nullValue 속성으로 지정한 특정한 값을 세팅 하므로써 DB 에 null 로 입력이 된 결과를 조회하여 assertNull 로 확인하고 있다. 위에서 empty String 의 nullValue 설정은 inline parameter 노테이션의 한계로 제대로 처리되지 않음을 확인하였으므로 참고하기 바란다.