You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Getting transaction for [...RollbackService.runtimeException]
call runtimeException
Completing transaction for [...RollbackService.runtimeException] after
exception: RuntimeException
Initiating transaction rollback
Rolling back JPA transaction on EntityManager
스프링 기본적으로 체크 예외는 비즈니스 의미가 있을 때 사용, 런타임(언체크) 예외는 복구 불가능한 예외로 가정
체크 예외 : 비즈니스 의미가 있을 때 사용
언체크 예외 복구 불가능한 예외
비즈니스 요구사항
주문을 하는데 상황에 따라 다음과 같이 조치
정상 : 주문시 결제를 성공하면 주문 데이터를 저장, 결제 상태로 완료 처리
시스템 예외 : 주문시 내부에 복구 불가능한 예외가 발생하면 전체 데이터를 롤백함
비즈니스 예외 : 주문시 결제 잔고가 부족하면 주문 데이터 저장, 결제 상태를 대기로 처리
=> 위와 같은 경우 고객에게 잔고 부족을 알리고 별도의 계좌로 입금 안내 진행
NotEnoughMoneyException
packagehello.springtx.order;
// 사용자 정의 예외 (체크 예외)publicclassNotEnoughMoneyExceptionextendsException {
// 생성자에서 메시지를 받아 부모 클래스의 생성자에 전달publicNotEnoughMoneyException(Stringmessage) {
super(message);
}
}
결제 잔고가 부족하면 발생하는 비즈니스 예외, Exception을 상속 받아 체크 예외가 됨
**Order **
packagehello.springtx.order;
importlombok.Getter;
importlombok.Setter;
importjavax.persistence.Entity;
importjavax.persistence.GeneratedValue;
importjavax.persistence.Id;
importjavax.persistence.Table;
@Entity// JPA 엔티티 지정@Table(name = "orders") // 테이블명을 orders로 지정@Getter@Setter// Lombok을 사용해 getter, setter 자동 생성publicclassOrder {
@Id// 기본 키 (Primary Key)@GeneratedValue// 자동 증가 값 사용privateLongid;
privateStringusername; // 주문자 이름 (특수 값: 정상, 예외, 잔고부족 가능)privateStringpayStatus; // 결제 상태 (대기, 완료 등)
}
JPA를 사용하는 Order 엔티티
예제를 단순하게 하기 위해 @Getter, @Setter 사용, 참고로 실무에서 엔티티에 @Setter를 남발해서 불필요한 변경 포인트를 노출하는 것은 좋지 않음
주의! @table(name = "orders")라고 했음, 테이블 이름을 지정하지 않으면 테이블 이름이 클래스 이름인 order가 됨, order는 디비 예약어(order by)여서 사용 불가, 그래서 orders라는 테이블 이름을 지정함
OrderRepository
packagehello.springtx.order;
importorg.springframework.data.jpa.repository.JpaRepository;
// JPA를 이용한 Order 엔티티의 Repository 인터페이스publicinterfaceOrderRepositoryextendsJpaRepository<Order, Long> {
}
스프링 데이터 JPA를 사용
OrderService
packagehello.springtx.order;
importlombok.RequiredArgsConstructor;
importlombok.extern.slf4j.Slf4j;
importorg.springframework.stereotype.Service;
importorg.springframework.transaction.annotation.Transactional;
@Slf4j// 로그를 위한 Lombok 어노테이션@Service// 스프링 서비스 빈 등록@RequiredArgsConstructor// final 필드를 자동으로 생성자 주입publicclassOrderService {
privatefinalOrderRepositoryorderRepository;
// JPA는 트랜잭션 커밋 시점에 Order 데이터를 DB에 반영@Transactionalpublicvoidorder(Orderorder) throwsNotEnoughMoneyException {
log.info("order 호출");
// 주문 저장orderRepository.save(order);
log.info("결제 프로세스 진입");
// 특정 username 값에 따라 예외 처리if (order.getUsername().equals("예외")) {
log.info("시스템 예외 발생");
thrownewRuntimeException("시스템 예외"); // 런타임 예외 발생 → 트랜잭션 롤백
} elseif (order.getUsername().equals("잔고부족")) {
log.info("잔고 부족 비즈니스 예외 발생");
order.setPayStatus("대기"); // 결제 보류 상태로 설정thrownewNotEnoughMoneyException("잔고가 부족합니다"); // 체크 예외 발생 → 기본적으로 트랜잭션 커밋
} else {
// 정상 승인 처리log.info("정상 승인");
order.setPayStatus("완료");
}
log.info("결제 프로세스 완료");
}
}
기본 : payStatus를 완료 상태로 처리하고 정상 처리 됨
예외 : RuntimeException("시스템, 예외") 런타임 예외가 발생한다
잔고부족
3-1. payStatus를 대기 상태로 처리
3-2. NotEnoughMoneyException("잔고가 부족합니다") 체크 예외가 발생
3-3. 잔고 부족은 payStatus 를 대기 상태로 두고, 체크 예외가 발생하지만, order 데이터는 커밋되기
를 기대
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
예외와 트랜잭션 커밋, 롤백 - 기본
**1. runtimeException() 실행 - 런타임 예외 **
실행 결과
checkedException() 실행 - 체크 예외
실행 결과
rollbackFor
@Transactional(rollbackFor = Exception.class)rollbackFor() 실행 - 체크 예외를 강제로 롤백
실행 결과
예외와 트랜잭션 커밋, 롤백 - 활용
비즈니스 요구사항
NotEnoughMoneyException
**Order **
OrderRepository
OrderService
를 기대
OrderServiceTest
complete()
assertThat(findOrder.getPayStatus()).isEqualTo("완료");runtimeException()
bizException()
assertThat(findOrder.getPayStatus()).isEqualTo("대기");검증 진행정리
NotEnoughMoneyException은 시스템에 문제가 발생한 것이 아니라, 비즈니스 문제 상황을 예외를 통해 알려줌All reactions