트랜잭션
일정 구간의 동작들이 모두 성공해야하는 일련의 과정으로,쪼갤 수 없는 업무 처리의 최소 단위
/ 보통 서비스 파일에서 관리함.
롤백
트랜잭션 내부에서 실행에 실패하면 지금까지 수행한 것을 모두 폐기하고 진행 초기 단계로 되돌리는 것
@Transactional
트랜잭션의 어노테이션으로 해당 어노테이션이 선언된 메서드를 트랜잭션으로 묶는 것. 클래스에 선언하면 클래스의 모든 메서드별로 각각 트랜잭션이 부여 됨. 실해하면 롤백하여 처음으로 돌아감
시나리오
의도적으로 오류
발생시키기(id = -1)@PostMapping("/api/transaction-test")
public ResponseEntity<List<Article>> transactionTest(@RequestBody List<ArticleForm>dtos){
}
@PostMapping 으로 생성 요청을 접수한다.
데이터 3개를 받을 transactionTest()라는 메서드를 만든다.
REST API
방식으로 POST 요청을 받기 위해 @RequestBody
어노테이션을 사용한다.
서버에서 응답을 할 때 데이터 생성 결과뿐만 아니라 상태 코드도 함께 보내주기 위해서 반환형은 ResponseEntity<List<Article>>
로 한다.
List<Article> createdList = articleService.createArticles(dtos);
return (createdList != null) ? ResponseEntity.status(HttpStatus.OK).body(createdList) : ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
createdList 라는 메서드는 Service에 만들고 동작하게 할 것이라 가정하고 미리 호출할 반환값을 createdList에 저장하도록 한다.
과정
stream 문법
리스트와 같은 자료구조에 저장된 요소를 하나씩 순회하면서 처리하는 코드 패턴이다.List<Article> articleList = new ArrayList<>; for (int i = 0; i < dtos.size(); i++) { ArticleForm dto = dtos.get(i); ArticleForm entity = dto.toEntity(); articleList.add(entity);
위 코드는 dto 리스트를 엔티티 리스트로 변환하는 코드인데 이 코드를 stream() 문법을 사용하면 아래와 같이 코드 길이를 줄일 수 있다.
// dto 묶음을 엔티티 묶음으로 변환하기
List<Article> articleList = dtos.stream()
.map(dto -> dto.toEntity())
.collect(Collectors.toList());
스트림 문법을 사용하지 않을 때
for(int i = 0; i < articleLsit.size(); i++){ Article article = articleList.get(i); articleRepository.save(article); }
스트림 문법을 사용할 때
// 엔티티 묶음을 DB에 저장하기 articleList.stream().forEach(article -> articleRepository.save(article));
//강제 예외 발생시키기
articleRepository.findById(-1L)
.orElseThrow(()-> new IllegalArgumentException("결제 실패!!"));
id 값이 -1인 데이터를 찾는다. JPA로 자동 생성된 id 값은 양수이므로 음수가 될 수 없다. orElseThorw()
메서드로 IllegalArgumentException
을 발생시키는데 "결제실패"라는 메시지도 함께 출력되기를 바란다. orElseThorw()
는 메서드 값이 존재하면 그 값을 반환하고, 그렇지 않으면 전달값으로 보낸 예외를 발생시킨다.
//결과 값 반환하기
return articleList;
간단하게 서비스 코드에 어노테이션만 추가하면 된다.
기존에 있는 데이터를 GET하여 확인함.
데이터를 넣고 싶은데 500 서버 에러가 발생한다.
결제 실패 메시지도 한번에 확인할 수 있다.
트랜잭션을 사용하지 않았다면 오류는 발생하지만 데이터는 정상적으로 들어가지는 현상이 발생할 수 있으며, 이는 프로젝트를 유지하는게 큰 장애가 발생할 수도 있다. 모든 동작이 정상적으로 동작해야하는 최소한의 단위가 있다면 트랜잭션을 적극적으로 활용해보자.
뒤지실래요? 눈삽으로 맞아보셨어요?