본문 바로가기

프레임워크/iBATIS

iBatis + Sysbase ASE 15.5 Unicode Column CRU 검증결과 및 적용방안

1. 검증결과: JBoss WAS 에서 JDBC를 연결할 때 다음과 같이 DataSource를 생성한다. 이 내용은 JBoss에 배포할 서버의 deploy/sybase-ds.xml 의 내용중 일부이다.

<?xml version="1.0" encoding="UTF-8"?>

<datasources>

  <local-tx-datasource>

    <jndi-name>jdbc/KFlowDS</jndi-name>

    <connection-url>jdbc:sybase:Tds:localhost:3000</connection-url>

    <driver-class>com.sybase.jdbc3.jdbc.SybDriver</driver-class>

    <connection-property name="CHARSET">eucksc</connection-property>

    …

    <exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.SybaseExceptionSorter</exception-sorter-class-name>

    <track-statements>true</track-statements>

    <metadata>

      <type-mapping>Sybase</type-mapping>

    </metadata>

  </local-tx-datasource>

</datasources>

여기서 핵심 내용은 JDBC의 속성중의 하나인 “CHARSET”“eucksc”로 설정함으로써 DB에서 읽거나 쓸 때 [iso1 : ISO-8859-1] – [eucksc: EUC-KR | KSC5601] 간 변환을 자동으로 처리해 준다. 문제는 DB 컬럼이 하나의 Charset이 아닌 경우 즉, Unicode 컬럼이 있는 경우에 대해서 검증이 필요했다.

첫 번째 조회의 경우, Java는 이미 Unicode(엄밀히 말하면 J2SE 5, 6Unicode 4.0을 사용함)를 사용하기 때문에 아무런 처리를 해주지않고 JDBC 설정만으로 해결이 가능하다.

참고: http://ko.wikipedia.org/wiki/유니코드

     [PDF] UnicodeData Types in Sybase® Adaptive Server® Enterprise 12.5

(http://www.sybase.com/content/1013476/4073UNI-chorwpaperv3.pdf)

두 번째 생성 및 변경의 경우, Sybase 아키텍처에는 문제가 없다고설명이 되어 있다. , 하나의 Charset이라면 위의 JDBC 설정만으로 간단하게 해결이 된다. 그런데 DB CharsetISO1 로 되어 있고 특정 컬럼만 Unicode로 되어있다면 Sybase JDBC 드라이버는 문자열을 Unicode-> ISO1로 변환을 하며 Unicode 컬럼에 맞지 않는 Charset이므로 깨져서 들어가게 된다. 문제는 이렇게 깨진 글자를읽어 들일 때 다시 eucksc로 변환을 한다는 것이다.

좀 복잡하게 설명을 했으나 어쨌든 기본적인 방법으론 이를 해결할 수 없다는 결론을 내렸다. 물론 JDBC Charset을지정하지 않고 순수하게 변환된 값을 넣어 줄 수도 있으나 개발자들이 처리해 줘야 할 것이 많아지고 유지보수 시점에도 어렵게 될 것이다.


해결방안:

이 문제를 해결하기 위해서는 iBatis 프레임워크가 Java Type, Jdbc type, Sql Type을 어떻게 처리하는지 이해해야만 한다. iBatis TypeHandler 라른 것을 이용하여 이 문제를해결하고 있다. 그런데 특정 DBMS의 경우 JDBC 표준을 따르지 않아서 프레임워크에서 처리하기 어려운 데이터 타입들이 존재한다. 예를 들면 Oracle LONG이나 CLOB, BLOB등은 표준을 따르지 않기로 유명하고 이를 처리하기 위한 다양한 방법이고안되었다. 현재 이 부분이 해결되었는지는 모를 일이다.

Sybase의 경우 UNICHAR,UNIVARCHAR, UNITEXT 등은 SQL type에서 조차 보이지 않는 듯 하다. 그러므로 JDBC 차원에서 해결하기 어렵다고 본다. 그래서 위의 Type TypeHandler를 확장한 CustomTypeHandler를 이용하게 되었고CustomTypeHandler에서 호출하는 TypeHandlerCallback 인터페이스를구현하게 되었다. 아래는 현재 구현된 모델을 보여준다.


위의 핸들러들을 이용하는 방법은 다음과 같으며 RI(ReferenceImplement: 참조구현)에서 소스코드를 확인 할 수 있다.

RiCommonEntity컴포넌트에서 /RiCommonEntity/src/main/resources/com/kyobobook/kflow/common/logic/dao/unicode-data-sqlmap-config.xml파일내용을 보면 다음과 같다.

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE sqlMapConfig PUBLIC"-//ibatis.apache.org//DTD SQL Map Config 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-config-2.dtd">

<sqlMapConfig>

  <settings cacheModelsEnabled="true"enhancementEnabled="true" lazyLoadingEnabled="true"useStatementNamespaces="true"/>

  <typeHandler javaType="java.lang.String"jdbcType="UNICHAR" callback="com.kyobobook.kflow.bizcommon.utility.dao.UnicharTypeHandlerCallback"/>

  <typeHandler javaType="java.lang.String" jdbcType="UNIVARCHAR" callback="com.kyobobook.kflow.bizcommon.utility.dao.UnivarcharTypeHandlerCallback"/>

  <typeHandler javaType="java.lang.String" jdbcType="UNITEXT" callback="com.kyobobook.kflow.bizcommon.utility.dao.UnitextTypeHandlerCallback"/>

  <sqlMap resource="com/kyobobook/kflow/common/logic/dao/sqlmap/RI_UnicodeData.xml"/>

</sqlMapConfig>

이제 UNICHAR, UNIVARCHAR, UNITEXT 타입을 처리할수 있는 준비가 되었으며 실제 SqlMap은다음과 같다.

...

<parameterMap id="insert-UnicodeData-param"class="UnicodeData">

  <parameter property="authorCode" jdbcType="CHAR" />

  <parameter property="authorName" jdbcType="VARCHAR" />

  <parameter property="authorNameUni" jdbcType="UNIVARCHAR" />

  <parameter property="authorEnglishName" jdbcType="VARCHAR" nullValue="NO_ENTRY"/>

  <parameter property="authorAnotherName" jdbcType="VARCHAR" nullValue="NO_ENTRY"/>

  <parameter property="authorAnotherNameUni" jdbcType="UNIVARCHAR"nullValue="NO_ENTRY" />

</parameterMap>

<insert id="registerUnicodeData"parameterMap="insert-UnicodeData-param">

insert intoIDPL..TM_STC_AUTR_UNI_TEST (

  autr_code

 ,autr_name

 ,autr_name_uni

 ,autr_ensn_name

 ,autr_atnm_name

 ,autr_atnm_name_uni

 

 ,autr_dvcd

 ,phtg_ysno

 

 ,use_ysno

 ,rgst_dttm

 ,rgsr_emnm

 ,amnd_dttm

 ,amnr_emnm

)

values (

  ?,?,?

 ,?,?,?

 ,'1'

 ,'Y'

 ,'Y'

 ,getDate()

 ,'1'

 ,getDate()

 ,'1'

)

</insert>

위와 같이 단지 parameterMap을 선언하고 jdbcType을 선언하는 것으로 Unicode가 처리된다. 여기서 주의할 내용은 nullValue="NO_ENTRY" 속성에 대한 이해인데 Nullable 한 컬럼에 대해서 실제 값이 Null인 경우 널을 허용하겠다는 표시를 해야 하며 “NO_ENTRY”가그런 의미로 사용된다.

이상으로 애플리케이션에서 Sybase Unicode Column 검증및 적용방안에 대한 설명을 마친다.

참고: http://imhotk.tistory.com/m/801<- Java에서 문자열과 Charset을 어떻게 다루는지 핵심사항을 쉽게 설명하고있다.

첨부: