MeetingService에서 Service단에 @Transactional 걸어줘야지! 라고 생각하고 MeetingService Class에다 단순하게 달아버렸다.
@Service
@RequiredArgsConstructor
@Transactional
public class MeetingService {
private final MeetingMapper meetingMapper;
public MeetingResponseDTO findMeetingOneById(Long meetingId) {
MeetingResponseDTO meetingResponseDTO = meetingMapper.findMeetingOneById(meetingId);
if(meetingResponseDTO == null) {
throw new IsExistCheckException(ErrorCode.NOT_FOUND_MEETING);
} else {
return meetingResponseDTO;
}
}
}
하지만 MeeringService 클래스에서 함수를 봤을 때 조회하는 기능이 많았고 추가하거나 수정하는 경우가 더 적었다.
이런 경우엔 굳이 모든 함수에 transaction이 적용될 필요는 없겠지?
Transactional의 ReadOnly 타입은 Boolean 타입으로 해당 트랜잭션이 읽기 전용 트랜잭션인지 아닌지 알려주는 역할을 한다.
읽기 전용 트랜잭션이란 말그대로 DB를 Update하거나 Delete 등과 같이 수정하는 트랜잭션이 아닌 검색하는 트랜잭션임을 알리는 것이다.
읽기 전용 트랜잭션임을 표시하는 이유는?
일관된 데이터들을 가져올 수 있다.
Transactional의 ReadOnly=True로 설정된 트랜잭션이 시작 후 접근하는 트랜잭션은 시작되기 이전 커밋된 트랜잭션에만 접근이 가능하다.
그렇기 때문에 ReadOnly가 적용된 트랜잭션에서 DB 값을 검색하여 조회하는 경우에는 다른 트랜잭션이 접근할 수 없기 때문에 일관된 데이터들을 조회할 수 있다.
불필요한 트랜잭션 ID 생성 방지
트랜잭션 ID란 MySQL의 InnoDB 엔진에서 트랜잭션이 시작될 때 부여되는 고유 ID이며 해당 트랜잭션이 롤백되거나 커밋될 때까지 유지되어 데이터가 변경될 때 그 시점의 데이터를 가져올 때 사용된다.
별도로 저장해주지 않아도 되는, 즉 롤백이 필요없는 SELECT 같은 읽기 작업 경우에는 이전 상태를 저장해줄 필요가 없을 것이다.
ReadOnly=True를 설정해줌으로써 불필요한 트랜잭션 ID가 부여되는 것을 방지할 수 있다.
(해당 내용은 MySQL, Oracle 기준이고, JPA에서 ReadOnly 설정이 더욱 중요하게 사용된다.)
@transactional가 Class에 적용된다면 Class 내의 Private, Protected Method 외 메소드에 트랜잭션이 적용된다.
@transactional을 메서드에 달아준다면 주석이 달린 특정 메서드에만 트랜잭션이 적용된다.
트랜잭션 어노테이션이 없는 메서드에서 트랜잭션이 있는 어노테이션을 호출해도 트랜잭션은 시작되지 않는다.
다시 본론으로 돌아와서 Transactional을 현 경우에 사용해야 될까요?
MeetingService에서 구현되는 작업은 관리자 권환 외 작업으로 다음과 같다.
=>이런 경우에는 클래스에 @transactional(ReadOnly=True) 설정을 하고 후에 소모임 신청 메서드에만 Transactinal 어노테이션을 달아주면 될 것이다.