기본적으로 LOB 유형의 데이터와 다른 유형의 데이터를 다루는 방식은 다르지 않다. 다만, LOB 유형의 데이터 조작이
필요한 경우에는 Query Service 속성 정의시 Lob Handler를 추가로 정의해 주어야 한다.
LobHandler 속성 정의에 대한 자세한 내용은
를 참고하도록 한다.
이 페이지에서는 Oracle 9i 이상, Oracle 8i로 구분하여 LOB 유형의 데이터를 다루는 방법에 대해 살펴볼 것이다.
Oracle 9i 이상일 경우
Query 서비스 속성 정의 파일 Sample
다음은 Query 서비스를 정의한
applicationContext-query-oracle.xml
과
Query 서비스에서 읽어들일 매핑 XML 파일의 위치를 정의한
applicationContext-query-sqlloader.xml
파일의 일부이다.
<bean name="oracle_queryservice" class="anyframe.core.query.impl.QueryServiceImpl">
<property name="jdbcTemplate" ref="oracle_jdbcTemplate"/>
<property name="sqlRepository" ref="sqlLoader"/>
<property name="lobHandler" ref="lobHandler"/>
<!-- 중략 -->
</bean>
<bean id="oracle_jdbcTemplate" class="anyframe.core.query.impl.jdbc.PagingJdbcTemplate">
<property name="dataSource" ref="oracle_datasource" />
</bean>
<bean id="nativeJdbcExtractor"
class="org.springframework.jdbc.support.nativejdbc.CommonsDbcpNativeJdbcExtractor"
lazy-init="true"/>
<bean id="lobHandler" class="org.springframework.jdbc.support.lob.OracleLobHandler" lazy-init="true">
<property name="nativeJdbcExtractor" ref="nativeJdbcExtractor"/>
</bean>
<!-- 중략 -->
<bean name="sqlLoader" class="anyframe.core.query.impl.config.loader.SQLLoader">
<config:configuration>
<filename>classpath:/services/query/mappings/mapping-lob-query.xml</filename>
<!-- 중략 -->
</config:configuration>
</bean>
<!-- 중략 -->
매핑 XML 파일 Sample
다음은 앞서 정의한 Query 서비스를 통해 로드된
mapping-lob-query.xml
로,
테이블 매핑 정보와 LOB 유형의 데이터를 다루는 다양한 쿼리문들을 포함하고 있다.
<queries>
<query id="insertLOB">
<statement>insert into longVarchar values(?,?,?)</statement>
<param type="INTEGER"/>
<param type="BLOB"/>
<param type="CLOB"/>
</query>
<query id="selectLOB">
<statement>select myblob, myclob from longVarchar where count = ?</statement>
<param type="INTEGER"/>
</query>
<query id="updateLOB">
<statement>update longVarchar set myblob = ?, myclob = ? WHERE count = ?</statement>
<param type="BLOB"/>
<param type="CLOB"/>
<param type="INTEGER"/>
</query>
<query id="deleteLOB">
<statement>delete from longVarchar WHERE count = ?</statement>
<param type="INTEGER"/>
</query>
</queries>
Query 서비스 테스트 코드 Sample
다음은 앞서 언급한 매핑 XML 파일에 정의된 LOB 유형의 데이터를 INSERT, SELECT, UPDATE, DELETE하는 소스 코드
QueryServiceTestLob.java
이다.
/**
* Query 서비스를 통해 DB에 신규 LOB 유형의 데이터를 입력하는 테스트 코드
*/
public void testInsertLOB() throws Exception{
IQueryService queryService = (IQueryService) context.getBean("oracle_queryservice");
String strVal1 = "0무궁화꽃이피었습니다";
String strVal2 = "1무궁화꽃이피었습니다무궁화꽃이피었습니다무궁화꽃이피었습니다무궁화꽃이피었습니다
무궁화꽃이피었습니다무궁화꽃이피었습니다무궁화꽃이피었습니다무궁화꽃이피었습니다
무궁화꽃이피었습니다무궁화꽃이피었습니다\n";
strVal2 += "2무궁화꽃이피었습니다무궁화꽃이피었습니다무궁화꽃이피었습니다무궁화꽃이피었습니다
무궁화꽃이피었습니다무궁화꽃이피었습니다무궁화꽃이피었습니다무궁화꽃이피었습니다
무궁화꽃이피었습니다무궁화꽃이피었습니다\n";
// skip
strVal2 += "30무궁화꽃이피었습니다무궁화꽃이피었습니다무궁화꽃이피었습니다무궁화꽃이피었습니다
무궁화꽃이피었습니다무궁화꽃이피었습니다무궁화꽃이피었습니다무궁화꽃이피었습니다
무궁화꽃이피었습니다무궁화꽃이피었습니다\n";
int result = queryService.create("insertLOB"
, new Object[] { new Integer(5), strVal1.getBytes() , strVal2 });
if( result == -1 ){
throw new Exception("LOB insert failed");
}
}
/**
* Query 서비스를 통해 DB에 입력된 LOB 유형의 데이터를 조회하는 테스트 코드
*/
public void testSelectLOB() throws Exception {
IQueryService queryService = (IQueryService) context.getBean("oracle_queryservice");
Collection result = queryService.find("selectLOB", new Object[] { new Integer(5) });
Iterator resultItr = result.iterator();
while (resultItr.hasNext()) {
Map binary = (Map) resultItr.next();
String myCLOB = (String) binary.get("myclob");
String myBLOB = new String((byte[]) binary.get("myblob"));
}
if(result.size() != 1){
throw new Exception("Select LOB failed");
}
}
/**
* Query 서비스를 통해 DB에 입력된 LOB 유형의 데이터를 수정하는 테스트 코드
*/
public void testUpdateLOB() throws Exception{
IQueryService queryService = (IQueryService) context.getBean("oracle_queryservice");
String strVal1 = "0장미꽃이피었습니다";
String strVal2 = "1장미꽃이피었습니다장미꽃이피었습니다장미꽃이피었습니다장미꽃이피었습니다
장미꽃이피었습니다장미꽃이피었습니다장미꽃이피었습니다
장미꽃이피었습니다장미꽃이피었습니다장미꽃이피었습니다\n";
strVal2 += "2장미꽃이피었습니다장미꽃이피었습니다장미꽃이피었습니다장미꽃이피었습니다
장미꽃이피었습니다 장미꽃이피었습니다장미꽃이피었습니다장미꽃이피었습니다
장미꽃이피었습니다장미꽃이피었습니다\n";
// skip
strVal2 += "30장미꽃이피었습니다장미꽃이피었습니다장미꽃이피었습니다장미꽃이피었습니다
장미꽃이피었습니다장미꽃이피었습니다장미꽃이피었습니다장미꽃이피었습니다
장미꽃이피었습니다장미꽃이피었습니다\n";
int result = queryService.create("updateLOB"
, new Object[] { strVal1.getBytes() , strVal2, new Integer(5)});
}
/**
* Query 서비스를 통해 DB에 입력된 LOB 유형의 데이터를 삭제하는 테스트 코드
*/
public void testDeleteLOB() throws Exception{
IQueryService queryService = (IQueryService) context.getBean("oracle_queryservice");
queryService.remove("deleteLOB", new Object[]{new Integer(5)});
}
앞서 소개된 샘플 테스트 코드를 포함하여 Query 서비스 소개 페이지에서 제공하는 모든 샘플 테스트 코드는 HSQL DB를
기반으로 실행된다. ( 단, ※ CallableStatement, LOB의 경우는 Oracle 9i, 10g를 기반으로 함. )
Oracle 8i일 경우
Query 서비스 속성 정의 파일 Sample
Spring에서 제공하는 Oracle LobHandler는 9i 이상에서만 적용 가능하므로, Oracle 8i 기반에서 LOB 유형의 데이터를 다루기
위해서는 Query 서비스 속성 정의시에 Anyframe에서 제공하는 LobHandler를 셋팅해 주어야 한다.
다음은 Query 서비스를 정의한
applicationContext-query-oracle8i.xml
의
일부로, Oracle 8i용으로 제공된 AnyframeOracle8iLobHandler를 정의한 부분이다.
<bean id="lobHandler" class="anyframe.core.query.impl.jdbc.lob.AnyframeOracle8iLobHandler"
lazy-init="true">
<constructor-arg value="net.sf.log4jdbc.ResultSetSpy"/>
<property name="nativeJdbcExtractor" ref="nativeJdbcExtractor"/>
</bean>
DriverSpy를 써서 실행되는 쿼리문을 로그로 남기고 있을 경우에는 LobHandler의 constructor argument를 정의하고,
아닐 경우에는 제거해도 된다.
DataSource 서비스 속성 정의 파일 Sample
defaultAutoCommit의 속성을 false로 변경한다.
<bean id="realDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:@localhost:1521:oracle"/>
<property name="username" value="system"/>
<property name="password" value="manager"/>
<property name="defaultAutoCommit" value="false"/>
</bean>
TransactionManager 속성 정의 파일 Sample
DataSource 서비스의 defaultAutoCommit 속성을 false로 설정했으므로, TransactionManager 셋팅이 필요하다.
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<tx:advice id="txAdvice"
transaction-manager="txManager">
<tx:attributes>
<tx:method name="*" propagation="REQUIRES_NEW"
rollback-for="Exception" />
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="executionMethods"
expression="execution(* anyframe.core.query..impl.QueryServiceImpl.*(..))" />
<aop:advisor advice-ref="txAdvice"
pointcut-ref="executionMethods" />
</aop:config>
매핑 XML 파일 Sample
신규 LOB 유형의 데이터를 INSERT하는 쿼리문의 경우에는 기존 쿼리문 정의와 다르게 lobStatement tag를 추가 정의해 주어야 한다.
<query id="insertBlobClobWithOra8i" isDynamic="false">
<statement>insert into binary values(?,empty_blob(),empty_clob())</statement>
<param type="INTEGER"/>
<lobStatement>
<statement>select myclob, myblob from binary where bin_id = ? for update</statement>
<param type="INTEGER"/>
</lobStatement>
</query>