Notice
Recent Posts
Recent Comments
Link
Welcome! Everything is fine.
INSERT 됐지만 테이블이 안보이는 문제(@Transactional) 본문
728x90
INSERT 됐지만 테이블이 안보이는 문제
댓글 작성 시, 아래와 같이 INSERT문은 제대로 실행된 것 같은데 DB에서는 comment 테이블이 보이지 않는 문제가 있었다.
@Transactional을 추가하지 않은 것이 원인이다. 트랜잭션이 자동으로 커밋되지 않아서 데이터가 DB에 반영되지 않았던 것이다. Service 계층에서 DB 작업을 수행할 때는 반드시 @Transactional 을 사용해 트랜잭션을 관리해야한다.
다음과 같이 @Transactional 을 붙인다.
@Transactional
public CommentResponseDto save(Long scheduleId, String email, CommentRequestDto dto) {
Schedule schedule = scheduleRepository.findByIdOrElseThrow(scheduleId);
Member member = memberRepository.findByEmailOrElseThrow(email);
Comment comment = new Comment(dto.getContents(), member, schedule);
Comment savedComment = commentRepository.save(comment);
return new CommentResponseDto(
savedComment.getId(),
savedComment.getContents(),
member.getUsername(),
savedComment.getCreatedAt(),
savedComment.getModifiedAt()
);
}
이렇게 해도 되지만, 어제 <연관 관계 매핑 세션>에서 튜터님께서 클래스 레벨에 우선@Transactional(readOnly = true)를 사용한다는 것이 기억나 다음과 같이 수정했다. 그리고 지난번 피드백을 다시 보니 다른 튜터님께서도 "트랜잭션 범위를 확실히 하기 위해 DB 업데이트와 관련된 모든 작업을 트랜잭션 내에서 처리하는 것이 좋다."라고 피드백을 남겨주셨다.
@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class CommentService {
private final CommentRepository commentRepository;
private final ScheduleRepository scheduleRepository;
private final MemberRepository memberRepository;
@Transactional
public CommentResponseDto save(Long scheduleId, String email, CommentRequestDto dto) {
Schedule schedule = scheduleRepository.findByIdOrElseThrow(scheduleId);
Member member = memberRepository.findByEmailOrElseThrow(email);
Comment comment = new Comment(dto.getContents(), member, schedule);
Comment savedComment = commentRepository.save(comment);
return new CommentResponseDto(
savedComment.getId(),
savedComment.getContents(),
member.getUsername(),
savedComment.getCreatedAt(),
savedComment.getModifiedAt()
);
}
}
이 문제를 해결하면서 잘 신경쓰지 않았던 부분의 개념을 확실히 익히게 되었다.
- 클래스 레벨의 @Transactional(readOnly = true) 적용
- 기본적으로 모든 메서드는 읽기 전용 트랜잭션 사용
- 변경 감지(Dirty Checking) 비활성화 → 불필요한 데이터 변경 감지 로직 생략 → 성능 최적화
- 조회 시 @Transactional이 없어도 동작하지만, @Transactional(readOnly = true)를 사용하면 성능이 최적화 되며 Lazy Loading(지연 로딩) 사용 시 트랜잭션 유지가 필요할 수 있음
- 쓰기 작업에는 @Transactional을 개별적으로 추가해야 함.
- 메서드 레벨에서 @Transactional을 명시하면, 클래스 레벨의 readOnly = true를 무시하고 데이터 변경이 가능한 트랜잭션으로 동작
'TIL' 카테고리의 다른 글
왜 엔티티에 Setter를 사용하면 안 될까? (0) | 2025.02.13 |
---|---|
Spring에서 @RequestBody를 사용할 때 주의해야 할 점 (0) | 2025.02.04 |
queryForObject() vs query() (0) | 2025.02.03 |
[TIL] 네트워크, HTTP와 HTTP의 특징 (0) | 2025.01.22 |
[TIL] 계산기 과제 해설, 와일드카드, 타입 이레이저 (0) | 2025.01.10 |