Ibatisclobblob
From JCFWiKi
iBATIS에서 CLOB이나 BLOB를 처리하기 위해서는 Spring 프레임워크의 applicationContext 설정파일에 lobhandler와 typeHandler에 대한 설정을 해주어야 한다.
오라클 환경에서 iBATIS CLOB을 이용하는 것은 Spring의 도움 없이는 4000자 (Oracle 9i driver) 또는 20000자(Oracle 10g driver) 이상의 데이터 입/출력은 되지 않았다. 더불어 iBATIS 2.3.0 이후부터는 자체 dao보다는 Spring을 쓸 것을 권장하면서 자신들의 dao를 기본 라이브러리에서 제외시키기도 하였다.
그러므로 iBatis에서 CLOB/BLOB을 사용하기 위해 Spring을 이용한 CLOB/BLOB 이용방법을 설명하도록 하겠다.
목차 |
[편집] CLOB/BLOB 사용하기
JCF 3.0에서 CLOB/BLOB을 사용하기 위해서는 다음과 같은 설정을 순서대로 진행하면 쉽게 사용할 수 있다.
- Spring 기본 설정
- Transaction 선언
- lobHandler와 native jdbc extractor 등록
- iBatis 기본 설정
- sql-config.xml에 typeHandler 등록
- sqlmap 작성
- Model 구성 (String/byte[])
- resultMap 구성
- statement 구성
[편집] Spring 기본 설정
[편집] transaction 선언
별도 connection이 필요한 LOB 핸들링 때문인지 transaction 선언을 하지 않으면 스프링에서 예외를 발생시킨다. 따라서 반드시 선언하고 호출할 때는 트랜잭션 프록시를 통해서 호출하도록 한다. 트랜잭션 관리를 적용하기 위해서 다음과 같은 순서대로 설정한다. 첫 번째로 applicationContext.xml에 다음과 같은 설정을 추가한다.
<!-- ========================= TX CONFIGURATION ========================= --> <tx:advice id="txAdvice" transaction-manager="txManager"> <tx:attributes> <tx:method name="get*" read-only="true"/> <tx:method name="find*" read-only="true"/> <tx:method name="view*" read-only="true"/> <tx:method name="save*" propagation="REQUIRED"/> <tx:method name="*" propagation="REQUIRED"/> </tx:attributes> </tx:advice> <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <aop:config> <aop:pointcut id="commonServiceOperation" expression="execution(* com.daewoobrenic.com..service.*Service.*(..))"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="commonServiceOperation"/> </aop:config>
두 번째로 LobHandler를 사용할 DataSource와 SqlMapClient를 설정한다.
따라서 각각의 SqlMapClientFactoryBean에는 lobHandler 프로퍼티를 추가해주어야 한다.
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" > <property name="driverClassName"><value>${driver}</value></property> <property name="url"><value>${url}</value></property> <property name="username"><value>${username}</value></property> <property name="password"><value>${password}</value></property> </bean> <bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean"> <property name="configLocation"> <value>classpath:/config/sqlmap-config.xml</value></property><property name="dataSource"><ref bean="dataSource" /></property><property name="lobHandler"><ref bean="oracleLobhandler"/></property> </bean>
[편집] lobHandler와 native jdbc extractor 등록
Spring에서 lobHandler를 사용하기 위해서는 실제 구현체인 oracleLobHandler와 Spring에서 제공하는 nativeJdbcExtractor를 다음과 같이 등록한다. nativeJdbcExtractor 등록 시 패키지 구조를 보면, Tomcat 5.5의 commons-dbcp가 애플리케이션의 jar와 충돌을 피하기 위해서 패키지가 변경되어 있다. 이 때문에 Spring 1.2.8 의 CommonsDbcpNativeJdbcExtractor는 동작하지 않는데, Spring 2.0 에서는 일반 배포본 dbcp나 톰캣버전의 dbcp에서 모두 동작하도록 바뀌었다.
<!-- ========================= LOB CONFIGURATION ========================= --> <bean id="nativeJdbcExtractor" class="org.springframework.jdbc.support.nativejdbc.SimpleNativeJdbcExtractor" lazy-init="true"/> <bean id="oracleLobhandler" class="org.springframework.jdbc.support.lob.OracleLobHandler" lazy-init="true"> <property name="nativeJdbcExtractor"> <ref local="nativeJdbcExtractor"/> </property> </bean>
[편집] iBatis 기본 설정
[편집] sql-config.xml에 typeHandler 등록
sqlmap-config*.xml 파일에서는 아래와 같이 CLOB/BLOB 핸들러를 추가해준다. 추가 시 주의사항은 sqmlmap resource를 선언하기 이전에 핸들러에 대한 선언이 이루어져야 한다.
<!-- ========== CLOB/BLOB Handler Setting ============= --> <typeHandler callback="org.springframework.orm.ibatis.support.ClobStringTypeHandler" jdbcType="CLOB" javaType="java.lang.String" /> <typeHandler callback="org.springframework.orm.ibatis.support.BlobByteArrayTypeHandler" jdbcType="BLOB" javaType="[B" />
위의 typeHandler는 Model에서 선언된 ClobString과 ByteArray을 DB(Oracle)의 CLOB과 BLOB으로 맵핑하는 역할을 수행한다.
BLOB의 경우에 sqlMap을 이용한 방법이 stream이 아니라서 용량이 큰 경우에 서버에 부담이 되기는 하지만 종전의 일반 VARCHAR string을 받아오던 방식과 크게 다름이 없어 적용에 부담이 적다. 위의 설정에서 - javaType="[B" 이라는 특이한 부분이 있는데, Debug 모드에서 byte[]의 javaType이 "[B"로 시작하는 것을 확인할 수 있다. 따라서 "[B" 문자를 사용하여 type mapping을 수행하기 때문에 글자 그대로 복사해 쓰도록 한다.
[편집] sqlmap 작성
- BLOB 처리의 경우
1. Model 구성 예 (BLOB으로 선언할 property에 대하여 byte[]로 선언. 아래 예에서는 proImage)
public class Dept { private String deptCode; private String deptName; private String maxCnt; private String univ; private String rowStatus; //BLOB과 매핑될 클래스의 변수 private byte[] proImage; ...... }
2. resultMap 구성 예
조회 결과를 담을 resultMap을 구성하는 경우에 특별한 설정이 없다. 따라서 기존에 iBatis에서 설정하던 방식 그대로 작성하면 된다. 여기서 proimage는 위와 같이 Model에서 byte[]로 데이터형이 선언되어 있다.
<typeAlias alias="dept" type="com.dept.model.Dept" /> <resultMap class="dept" id="resultMap-dept"> <result property="deptCode" column="dept_cd" /> <result property="deptName" column="dept_name" /> <result property="maxCnt" column="max_cnt" /> <result property="univ" column="univ" /> <result property="proImage" column="proimage" /> </resultMap>
3. insert 구문 예
statement 구성 시에도 기존의 iBatis sqlmap 구성방법과 같다.
<!-- Dept 저장--> <statement id="insertDept" parameterClass="dept"> <![CDATA[ INSERT INTO DEPT(dept_cd, dept_name, max_cnt, univ, proimage) VALUES(#deptCode#, #deptName#, #maxCnt#, #univ#, #proImage#) ]]> </statement>
4. select 구문 예
<!-- Dept 조회--> <statement id="findDepts" parameterClass="string" resultMap="resultMap-dept"> <![CDATA[ SELECT dept_cd, dept_name, max_cnt, univ, proimage FROM DEPT ]]> </statement>
- CLOB 처리의 경우
다음 IMAGEDB라는 테이블 구조에서 보았듯이 DESCRIPTION 필드가 CLOB형으로 구성되어 있는 것을 확인할 수 있다.
1. Model 구성 예 (BLOB으로 선언할 property에 대하여 byte[]로 선언. 아래 예에서는 proImage)
public class Image { private String fileName; private byte[] content; private String description; ...... }
2. resultMap 구성 예
<resultMap id="imageDBResult" class="image"> <result property="fileName" column="imagename"/> <result property="content" column="content"/> <result property="description" column="description"/> </resultMap>
3. insert 구문 예
<insert id="insertImage" parameterClass="image"> INSERT INTO imagedb (imagename, content, description) VALUES (#fileName#, #content#, #description#) </insert>
4. select 구문 예
<select id="selectImages" parameterClass="string" resultMap="imageDBResult"> SELECT imagename, content, description FROM imagedb </select>
