백엔드/Mybatis
MyBatis 사용 시 Bulk insert 시 PK 추출 주의할 사항
정진킴
2024. 1. 12. 16:11
Mybatis를 이용하여 insert 쿼리 수행 시 방금 Insert 된 PK를 가져오기 위해 insert 후 select 하는 로직을 구현해 본 경험이 있을 것이다.
하지만 insert 태그 속성 중에 "useGeneratedKeys", "keyProperty" 를 이용하면 select를 할 필요가 없다.
<insert id="registerEdocProperty"
parameterType="com.domain.Edoc"
useGeneratedKeys="true"
keyProperty="edocPropertySeq">
INSERT INTO [EdocProperty] (
[edocSeq], [propertyName], [propertyValue]
)
VALUES (
#{edocSeq}, #{propertyName}, #{propertyValue}
)
</insert>
- Insert 가 수행되면 Member 객체에 seq 변수에 자동으로 방금 insert된 PK 값이 저장된다.
- 단 AutoIncrement 인 PK 여야 한다.
- 그러나 List 형태의 데이터를 insert 하는 경우 Batch 방식으로 한번에 넣기 위해 아래와 같이 foreach 태크를 이용하여 구현하는 경우도 있다.
- 결과는 동일하게 Insert 되지만 PK 를 써야하는 상황에서는 심각한 문제가 있다.
<insert id="registerEdocProperty"
parameterType="com.domain.Edoc"
useGeneratedKeys="true"
keyProperty="edocPropertySeq">
INSERT INTO [EdocProperty] (
[edocSeq], [propertyName], [propertyValue]
)
VALUES
<foreach item="item" collection="list" separator=",">
(
#{edocSeq}, #{propertyName}, #{propertyValue}
)
</foreach>
</insert>
- 위의 이미지를 보면 알 수 있듯이 edocPropertySeq 가 pk 인데 0 번째 인덱스의 PK 에 3 이 들어가고 나머지는 0으로 셋팅되는 현상을 발견했다.
결론은, PK를 사용해야 하는 경우 <foreach> 구문을 이용해서 Batch성으로 insert를 하게 되면 pk 값이 제대로 셋팅이 안되기 때문에 mapper를 여러번 호출하여 PK 값이 해당 객체에 셋팅되도록 구현하자!!