@Transactional
public List<BoardFileDto> insertBoard(BoardDto boardDto,
MemberDto loginMember,
MultipartHttpServletRequest multipartHttpServletRequest) throws Exception {
//board insert
log.debug("board insert");
boardDto.setCreatorName(loginMember.getName());
boardDto.setCreatorId(loginMember.getLoginId());
boardMapper.insertBoard(boardDto);
//file insert
log.debug("file insert");
List<BoardFileDto> list = fileUtils.parseFileInfo(boardDto.getBoardIdx(), boardDto.getCreatorId(), multipartHttpServletRequest);
//if file has error BoardFileDto.hasError -> true
//저장 성공한 애들 리스트
List<BoardFileDto> successList = list.stream()
.filter(h -> h.isHasError() == false)
.collect(Collectors.toList());
//저장 성공한 애들만 DB에 목록 넣기
if (list.isEmpty() == false){
try {
boardMapper.insertBoardFileList(successList);
int i = 10/0; //의도적 오류
} catch (Exception e){
//파일 삭제 코드
fileUtils.deleteFileList(successList);
throw new Exception("파일 저장중 에러 발생");
}
}
return list;
}
위의 코드는 게시글 작성 + 파일 업로드 서비스중 일부이다.
일단 트랜잭션 처리가 되어있고,
//board insert 부분은 게시글의 제목과 내용을 넣는 부분
//file insert 부분은 게시글의 첨부파일을 로컬 디렉토리에 저장하고 그 리스트를 반환하는 부분이다
그리고 오늘 처리할 부분은 그 작업이 다 끝난 후 boardinfo 테이블에 그 리스트를 저장하는 부분이다.
위 코드에서 발생한 오류
나의 의도 : 만약 오류가 발생하면, 파일 삭제 코드를 실행하고, 에러를 발생시켜 transaction처리한다.
결과적으로 db와 로컬 저장소 모두 같이 트랜잭션 처리가 된다.
오류 : Exception에 Transaction이 작동 하지 않는다.
이유 : 스프링에서는 @Transactional을 사용한 Checked Exception은 롤백되지 않습니다.
그 이유는 EJB에서의 관습 떄문이라고 하는데... 관습적인 이유인가보다
즉 Unchecked Exception으로 바꿔주면 된다.
해결 방법 : throw new RuntimeException("")으로 바꿔주면 된다.
트랜잭션을 작동 시키고 싶을 때는 RuntimeException을 발생 시키자
'SpringBoot > [SpringBoot]' 카테고리의 다른 글
[SpringBoot] 파일 다운로드의 두 가지 방법 (0) | 2022.11.24 |
---|---|
[SpringBoot] Thymeleaf 반복문 첫번째 요소만 다르게 하기 (0) | 2022.11.17 |
[SpringBoot] 웹에 이미지를 표시하는 두가지 방법 (0) | 2022.11.17 |
[SpringBoot] 로컬 파일 저장과 DB를 같이 트랜잭션 시키기 (0) | 2022.11.16 |
[Interceptor] 인터셉터를 통한 로그인 체크 / 접근 관리 (0) | 2022.11.14 |