Creative Wrong Answer

오라클 프로시저 호출 +1


아이바티스가 3으로 버전업 되면서 구글그룹으로 합류하고 이름이 myBatis로 변경되었다.
공식 홈페이지도 http://www.mybatis.org/ 로 변경되었고.. 2010년 8 월에 3.02 버전이 나왔다.
이전에 DTD가 http://www.ibatis.com 으로 되어있어서 에러가 난다면.. http://apache.ibatis.com 으로 변경하면 된다고 한다.

기존 버전사용자의 마이그레이션은 간단하다고 하는데.. 기존에 운영하던 프로젝트를 버전업 해보고나서 포스팅 예정이다.


iBatis를 사용해서 프로시저를 호출하는 것은 다른 statement(select, update.. )를 호출하는 것처럼 간단하다..
문제는 파라미터의 세팅이다. 호출이야 <procedure> 태그만 적어주면 되는데 파라미터가 꽤나 귀찮게 하는 경우가 생긴다.

1. 자바에서 호출하는 경우

자바에서 호출하는 경우는 CallableStatement 를 사용하게 된다.

CallableStatement cstmt = conn.prepareCall("{call PROC_BL_TO_UTM(?,?,?,?)}");
cstmt.setString(1, "37.465687");
cstmt.setString(2, "127.249481");
cstmt.registerOutParameter(3, OracleTypes.FLOAT);
cstmt.registerOutParameter(4, OracleTypes.FLOAT);
cstmt.execute();
uTmx = cstmt.getFloat(3);
uTmy = cstmt.getFloat(4);

in 파라미터와 out 파라미터를 구분해서 넘겨주고 execute 시키면 가뿐하게 넘어온다.

2. iBatis에서 프로시저 호출하기

SqlMap 설정

<parameterMap class="map" id="blParam">
  <parameter property="p_latitude" jdbcType="VARCHAR" javaType="java.lang.String" mode="IN"/>
  <parameter property="p_longitude" jdbcType="VARCHAR" javaType="java.lang.String" mode="IN"/>
  <parameter property="p_utmx" jdbcType="DECIMAL" javaType="long" mode="OUT"/>
  <parameter property="p_utmy" jdbcType="DECIMAL" javaType="long" mode="OUT"/>
 </parameterMap>
  
 <procedure id="bl_to_utm" parameterMap="blParam">
  <![CDATA[
   {call PROC_BL_TO_UTM(?,?,?,?)}
  ]]>
 </procedure>


java 설정

Map map = new HashMap();
map.put("p_latitude",vo.getX_latitude());
map.put("p_longitude", vo.getX_longitude());
sqlMapper.update("VocIphone.bl_to_utm", map );

String utmx = map.get("p_utmx").toString();
String utmy = map.get("p_utmy").toString();


SqlMap 쪽에서 parameterMap 으로 설정해놓은 형식으로 프로시저에 전달되고 리턴은 데이터를 실어서 날렸던 맵으로 돌아온다..
sqlMapper를 실행시킬때 update / queryForObject / queryForList 를 사용할수 있으니 리턴 타입에 맞춰서 사용하면 된다.

out을 리스트로 받는 경우 resultMap을 설정해서 List 형태로도 받을수 있다.

<parameter property="result" jdbcType="ORACLECURSOR" javaType="java.sql.ResultSet" resultMap="resultParam" mode="OUT"/>

resultMap을 설정해주고 resultMap에서 property와 column이름을 설정해주고 class를 미리 만들어놓은 VO객체로 넣어주면 해당항목의 리스트로 프로시저 실행결과가 리턴된다.

3. 주의사항

sqlMap에서 프로시저를 호출할때

<procedure id="bl_to_utm" parameterMap="blParam">
   {
     call PROC_BL_TO_UTM(?,?,?,?)
    }
 </procedure>

위의 코드처럼 중괄호를 적어놓으면 에러가 난다..;; 괜히 보기 편하게 만든다고 했다가 삽질하게 된다.

파라미터의 타입

만약 프로시저의 파라미터가 Number 타입이라면.. OUT 파라미터 정의에서 Number라고 쓰면 에러가 난다.....;;;
오라클의 경우 프로시저 내부에서 Number를 BigDecimal로 변환해서 사용한다고 한다. 따라서 아래처럼 적으면 에러가 난다.

<parameter property="p_utmy" jdbcType="NUMBER" javaType="java.util.Number" mode="OUT"/>ERROR


<parameter property="p_utmy" jdbcType="DECIMAL" javaType="long" mode="OUT"/>

이런 형태로 적어줘야 정상적으로 실행된다. 이것때문에 하루를 꼬박 구글링과 삽질로 보냈다..
오라클 디비를 내가 만든것도 아니고 이런걸 어떻게 알지..-ㅅ-;;

iBatis로 할수 있는게 참 많다.. Result 를 받는 시점에서 rowHandler를 설정해서 xml 트리형태의 데이터를 한방에 가져올수도 있고... 복잡한 파라미터와 조건에 맞춘 쿼리도 쉽게 뽑아내준다..
iBatis 파이팅 -ㅅ-!?;;
저작자 표시 비영리 동일 조건 변경 허락
신고

Comment 1

  • bluebird 2011.11.22 00:06 신고

    궁금한게있습니다. 위예제에서 프로시저에서 넘어온 out 변수를 맵에 담았는데요
    자바빈즈에 프로퍼티명을줘서 자바빈즈에 담기게 할수는 없나요?

    <parameterMap class="패키지명.자바빈즈" id="blParam">
    <parameter property="빈즈 프로퍼티명" jdbcType="DECIMAL" javaType="long" mode="OUT"/>

    이런식으로 작성했을때 프로시저 호출은되도 out변수에 담긴값이 빈즈의 프로퍼티에 세팅이
    안되더라구요;;