로그에 아래와 같은 에러메시지가 출력되고

2007-10-06 11:37:57,843 INFO [org.springframework.jdbc.support.SQLErrorCodesFactory] - <SQLErrorCodes loaded: [DB2, Derby, H2, HSQL, Informix, MS-SQL, MySQL, Oracle, PostgreSQL, Sybase]>
2007. 10. 6 오전 11:37:57 org.apache.catalina.core.StandardWrapperValve invoke
심각: Servlet.service() for servlet test_spring threw exception
java.lang.IllegalArgumentException
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
 at java.lang.reflect.Method.invoke(Unknown Source)
 at com.ibatis.sqlmap.engine.accessplan.PropertyAccessPlan.setProperties(PropertyAccessPlan.java:46)
 at com.ibatis.sqlmap.engine.exchange.JavaBeanDataExchange.setData(JavaBeanDataExchange.java:112)
 at com.ibatis.sqlmap.engine.mapping.result.BasicResultMap.setResultObjectValues(BasicResultMap.java:373)
 at com.ibatis.sqlmap.engine.mapping.statement.RowHandlerCallback.handleResultObject(RowHandlerCallback.java:64)
 at com.ibatis.sqlmap.engine.execution.SqlExecutor.handleResults(SqlExecutor.java:382)
 at com.ibatis.sqlmap.engine.execution.SqlExecutor.handleMultipleResults(SqlExecutor.java:301)
 at com.ibatis.sqlmap.engine.execution.SqlExecutor.executeQuery(SqlExecutor.java:190)
....

화면엔...
Error setting property 'setXXX' of 어쩌구 저쩌구 나오는 경우...의 대부분은
일종의 NullPointerException이다.

<resultMap ... 하위의
<property 에 nullValue를 처리해주지 않은 곳에 null이 들어갈 경우 발생한다.

<resultMap class="test.Member" id="memberResult" >
  <result property="id" column="id" />
  <result property="name" column="name"/>
<result property="age" column="age" nullValue="0"/>

테이블 컬럼에 not null이 아닌 항목은 위와 같이 nullValue처리를 꼭 해주어야 한다는 사실..




오라클을 사용하여 프로그램할땐 Sequence의 nextVal을 이용하여 insert하고 해당 값으로 관련된 다른 테이블에 사용하곤 했었는데...
MySQL이나 MSSQL은 auto_increment, identity를 이용하여 디비 내부적으로 자동증가하여 그 부분을 어떻게 처리할까 고민하곤 했었다. 내부적으로 SCOPE_IDENTITY(), LAST_INSERT_ID() 함수를 이용하여 가져올수 있다는 것을 나중에서야 알았따.

이제 본론으로.... iBatis를 이용할때 이부분 더 좋게 지원해준다.
<selectKey>를 이용하면 프로그램쪽에서 한번더 select하는 번거로움을 덜어주고 성능면에서도 조금은 도움을 줄것으로 생각된다.

* 키값이 자동증가인 경우 ...
<insert id="insertId">
  insert into MEMBER (MBR_ID, NAME) values
    ( #mbrId#, #name# )
  <selectKey keyProperty="memberSeq" resultClass="int">
    SELECT  LAST_INSERT_ID()
  </selectKey>
</insert>
Integer result = sqlMap.insert("insertId", member);

이렇게 처리하면 result에 마지막으로 추가된 키값이 담기게 된다.

* 키값이 자동증가가 아닌경우...

<insert id="insertId">
  <selectKey keyProperty="memberSeq" resultClass="int">
    SELECT MAX(MBR_SEQ) + 1 FROM MEMBER
  </selectKey>
  insert into MEMBER (MBR_SEQ, MBR_ID, NAME) values
    ( #memberSeq#, #mbrId#, #name# )
  <selectKey keyProperty="memberSeq" resultClass="int">
    SELECT  LAST_INSERT_ID()
  </selectKey>
</insert>

이와 같이 처리하면 끝.


ORM이란개 Object Relational Mapping 이라고...
그중에 하나의 테이블이 아닌 여러개의 테이블을 조인한 Mapping은 어떻게 할까.. 고민...그러다가 알게 된 것이다.

<sqlMap namespace="Member">
    <resultMap id="get-member" class="member">
    <result property="id" column="id"/>
    <result property="name" column="name"/>
  </resultMap>


  <resultMap id="get-member-result" class="member" extends="get-member"><== a) Main List
    <result property="user.id" column="user_id"/>
    <result property="user.password" column="password"/>
    <result property="studyHistory" column="{id=id}" select="getStudyList" />  <== b) SubList
  </resultMap>

member와 user는 SqlMapConfig.xml에서 alias로 지정한 것이다.

<typeAlias alias="study" type="com.test.domain.Study"/>
   <typeAlias alias="member" type="com.test.domain.Member"/>
   <typeAlias alias="user" type="com.test.domain.User"/>
</typeAlias>

 

그래서 가져온 결과물은... 요렇게 해서 가져온다.
  <select id="getMemberList" resultMap="get-member-result">
  <![CDATA[
    select a.seq as id, a.name as name,
      a.user_id as user_id, b.password as password,
    from member a, user b
    where a.user_id=b.user_id
  ]]>

</select>

Member class에서 User Object를 선언하고 getXXX, setXXX 메소드를 추가한다.

<select id="getStudyList" parameterClass="study" resultMap="get-study-result">
  <![CDATA[
    select a.id, a.lec_num, a.lec_name
    from study a
    where a.id = #id#
  ]]>
</select>

이것은 앞의 getMemberList 를 실행하면서 각 회원의 getStudyList목록을 List형태로 리턴하게 된다.

검색조건에 추가할라믄 column="{id=id,seq=seq}"  와 같은 형식으로 추가한다.

ㅎㅎㅎ 참 좋은 기능이다. 그럼그렇지 이런게 안될리 없지... 잠시나마 ORM 보다 걍 막쓰는 JDBC가 더 좋다고 외쳐보려던 나의 생각을 다시 돌려본다.....





« PREV : 1 : 2 : 3 : 4 : 5 : NEXT »