DB의 Table의 관계가 child의 FK가 parent의 auto_increament 속성의 PK와 연결되어 있다고 하겠습니다.
이경우 Insert 행위시에 parent에 대해서 child도 함께 Insert 된다고 가정하겠습니다. 이럴 경우 parent를 Insert처리하고 Select를 던져서 해당 key정보를 얻어야 child를 Insert할 수 있습니다. 이럴 경우 iBatis에서 설정하는 방법을 알아보겠습니다.
sqlMap xml설정을 다음과 같합니다.
<insert id="insertContent" parameterClass="content">
<![CDATA[
INSERT INTO CONTENT (
CREATED_DATE, TITLE, CONTENT, CONTENT_TYPE
) VALUES (
now(), #title#, #content#, #contentType#
)
]]>
<selectKey keyProperty="seqId" resultClass="int">
SELECT LAST_INSERT_ID()
</selectKey>
</insert>
위와 같이 설정하고 소스부분에서 다음과 같이 작성합니다.
Content content = new Content();
content.setTitle("selectKey 테스트");
content.setContent("<selectKey.../>에 대하여 테스트 합니다.");
content.setContentType("NN");
Integer seqId = contentService.insertContent(content);
이 결과는 Integer Type의 객체로 Insert된 sequence Key 값을 가져옵니다.
위 설정에서 <selectKey keyProperty="seqId" resultClass="int"> 부분을 살펴 보면 seqId는 Content 객체의 Integer Type의 인스턴스 변수입니다. native Type (int)으로 해도 문제가 발생하지 않는 것으로 알고 있습니다. 소스 부분에서
Integer seqId = contentService.insertContent(content);
이 부분에서 반드시 Integer Type으로 받아야 합니다. 그렇지 않으면 CastingException이 발생하게 됩니다. (native Type int로 받아도 문제 없습니다^^)
수행된 log를 출력하면 다음과 같습니다.
[COTAMOT] DEBUG,[2008-02-14 16:44:52,006],[main],(JakartaCommonsLoggingImpl.java:27),{conn-100000} Connection
[COTAMOT] DEBUG,[2008-02-14 16:44:52,136],[main],(JakartaCommonsLoggingImpl.java:27),{pstm-100001} Executing Statement:
INSERT INTO CONTENT (
CREATED_DATE, TITLE, CONTENT, CONTENT_TYPE
) VALUES (
now(), 'selectKey 테스트', '<selectKey.../>에 대하여 테스트 합니다.', 'NN'
)
[COTAMOT] DEBUG,[2008-02-14 16:44:52,346],[main],(JakartaCommonsLoggingImpl.java:27),{pstm-100002} Executing Statement:
SELECT LAST_INSERT_ID()
Insert가 수행되고 다음에 Select 가 수행됨을 알수 있습니다.
참고로 sequence 값을 가져오는 방법을 DBMS별로 나열하면 다음과 같습니다.
oracle - nextval(#sequence#)
mssql - SCOPE_IDENTITY()
mysql - LAST_INSERT_ID()
이렇게 되면 child를 Insert 처리 할 때 FK 값을 얻는데 간편합니다.