JeongJin's Blog

MyBatis 사용 시 Bulk insert 시 PK 추출 주의할 사항 본문

백엔드/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 여야 한다.
     

edocPropertySeq 가 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

  • 위의 이미지를 보면 알 수 있듯이 edocPropertySeq 가 pk 인데 0 번째 인덱스의 PK 에 3 이 들어가고 나머지는 0으로 셋팅되는 현상을 발견했다.

결론은, PK를 사용해야 하는 경우 <foreach> 구문을 이용해서 Batch성으로 insert를 하게 되면 pk 값이 제대로 셋팅이 안되기 때문에 mapper를 여러번 호출하여 PK 값이 해당 객체에 셋팅되도록 구현하자!!