메서드
Save
Save 메서드를 사용하면 엔티티를 DB에 저장할 수 있습니다. Save 메서드를 사용할 때 flush 또는 commit 메서드에 대한 명시적인 호출이 이루어지기 전까지는 저장 작업과 관련된 데이터가 DB에 반영되지 않습니다.
Flush
Flush는 영속성 컨텍스트에 존재하는 엔티티의 변경 내용을 DB에 반영하는 것을 말합니다. Transaction commit 이 일어날 때, flush 가 동작하고 이때 쓰기 지연 저장소에 쌓아 놨던 insert, update, delete 쿼리들이 실행됩니다.
SaveAndFlush
Save 메서드와 다르게 실행 중(트랜잭션)에 즉시 데이터를 flush 합니다.
쓰기 쿼리의 호출 시점 차이
Save
@Transactional
public void saveAndFlushTest(OrderInfo orderInfo) {
try {
// 1. 주문 정보 생성
OrderInfo orderInfo = OrderInfo.builder().orderId(orderId).build());
// 2. 주문 정보 저장
orderInfoRepository.save(orderInfo);
} catch (RuntimeException e) {
throw new ApiException(ORDER_ERROR);
}
System.out.println("Pass try catch!!!");
}
order_Info 테이블의 PK는 orderId이고, PK를 직접 할당합니다. 이 경우 저장하려는 엔티티의 PK값과 동일한 데이터가 DB에 존재한다면 무결성 에러가 발생합니다. 따라서 RuntimeException catch 블록에서 예외처리가 될 것이라고 예상할 수 있습니다.
그러나 예외 상황을 발생시키면 catch 블록에서 예외 처리가 되지 않습니다. Save 메서드 이후에도 모든 서비스 로직이 실행된 것을 확인할 수 있습니다. Insert 문은 save(SaveEventListener) 후에 내부 쿼리 저장소에 저장이 됐다가 이후 flush(FlushingEventListener) 후에 수행됩니다.
따라서 flush는 서비스의 로직이 모두 수행된 후에 진행되기 때문에 try catch 문으로 save 메서드의 예외처리를 할 수 없습니다.
SaveAndFlush
SaveAndFlush 메서드는 호출 이후에는 바로 flush 가 발생한 것을 확인할 수 있습니다. 이로 인해 insert 문이 바로 실행됐고 무결성 에러(DataIntegrityViolationException)가 발생함으로써 catch 블록에 의해 예외처리가 됩니다.
참고자료
'Spring' 카테고리의 다른 글
AbstractAggregateRoot 로 도메인 이벤트 등록하기 (1) | 2023.12.05 |
---|---|
MapStruct (0) | 2023.11.28 |
Save 메서드 동작 원리 (1) | 2023.11.28 |
Valid 어노테이션 커스텀해서 사용하기 (0) | 2023.10.22 |
Valid, Validated 어노테이션 (0) | 2023.09.24 |