본문 바로가기
관리자

Programming-[Backend]/Database

id 설정하기. batchInsert, UUID, GenerationType.IDENTITY

728x90
반응형

 

상황

스프링부트 + JPA 조합에서 batchInsert를 해야하는 상황

 

 

GenerationType.IDENTITY: batchInsert 불가

public void saveMessages(dto) {
    List<Message> messages = new ArrayList<>();
    dto.getMsgData().forEach(msgData -> {
        Message newMessage = new Message(
                UUID.fromString(msgData.getMsgKey()),
                null,
                null,
                msgData.getSenderNumber(),
                msgData.getReceiverNumber(),
                false,
                null
        );
        messages.add(newMessage);
    });
    messageCustomRepository.batchUpsert(messages);
}
@Repository
@RequiredArgsConstructor
public class MessageCustomRepositoryImpl implements MessageCustomRepository {

    private final EntityManager entityManager;

    @Override
    public void batchUpsert(List<Message> messageList) {
        messageList.forEach(entityManager::persist);
    }
}

 

 

위 코드와 같이 batchInsert를 해야하는 상황이라면 id가 GenerationType.IDENTITY로 설정된 경우에는 불가하다. 왜냐하면 DB에서 Id를 생성하고 관리하는 전략인데, 실제 DB에 id 값을 insert 하기 전까지는 다음 id값이 몇인지 알기 어렵기 때문이다. 

 

GenerationType.Sequence로 지정하더라도 batchInsert로 활용하기에는 무리가 있다.

 

ref.)

https://techblog.woowahan.com/2695/

 

 

 

UUID 사용하기

이전 글에서  uuid를 사용하는 것은 정렬이 안되는 문제가 있다고 했었다.

https://whitepro.tistory.com/1055

 

그런데, 정렬이 안된다고 사용을 안해야되는 것은 아니다. 정렬이 필요없고, batchInsert를 해야하는 경우라면 UUID로 사용하고 정렬은 created_at을 Index로 잡아서 처리하면 된다.

 

@Entity
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "message", indexes = {
    @Index(name = "idx_message_key", columnList = "message_key"),
    @Index(name = "idx_receiver_mobile_number", columnList = "receiver_mobile_number"),
    @Index(name = "idx_created_at", columnList = "created_at")
})
public class Message extends BaseEntityAbstract {

    @Id
    @Column(nullable = false, unique = true)
    private UUID messageKey = UUID.randomUUID();

    @Column(length = 50)
    private String type = "NONE";

    @Column(length = 20)
    private String senderMobileNumber;

    @Column(length = 20)
    private String receiverMobileNumber;

    @Column(nullable = false)
    private boolean sentSuccess = false;

    @Column(length = 2048)
    private String webhookResponse = "NONE";
}

 

 

배치 인서트를 할 때는 mysql의 경우 반드시 아래 rewriteBatchedStatements=true 옵션을 DB 연결 쿼리 파라미터로 주어야한다.

jdbc:mysql://localhost:3306/{DB명}?rewriteBatchedStatements=true&....기타 옵션들

 

728x90
반응형