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
반응형
'Programming-[Backend] > Database' 카테고리의 다른 글
JPA, ddl-auto, MYSQL, index 등 테이블 생성 기초 정리 (0) | 2025.01.12 |
---|---|
[TIL] TSID를 사용해야하는가? 왜 Id값은 Long(bigint)로 하는가? (1) | 2024.12.07 |
[TIL] MySQL 사용 관련 주요 팁 모음: 타입, INET_ATON, FK 물리적으로 걸지 않기 (0) | 2024.08.26 |
[경험 요약] Atomikos multi-database transaction 묶기 (0) | 2024.05.04 |
[TIL][link] DB Connection Pooling, context manager (0) | 2023.09.18 |