Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
Tags
- 안드로이드스튜디오
- 티스토리챌린지
- 혼공단
- 코틀린
- 안드로이드
- Android
- 알고리즘
- 카카오코테
- 혼공파
- select
- 프로그래머스
- join
- 기술면접
- Kotlin
- 인프런
- 자바
- java
- 정보처리기사
- SQL
- 혼공챌린지
- doitandroid
- MySQL
- 스터디
- Til
- groupby
- 정처기
- 코테
- CS
- 오블완
- 자료구조
Archives
- Today
- Total
Welcome! Everything is fine.
[Spring] 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' 카테고리의 다른 글
[Git] 로컬 브랜치에서 pull 할 때 에러 발생 - stash로 임시 커밋하기 (0) | 2025.02.18 |
---|---|
[Spring] 왜 엔티티에 Setter를 사용하면 안 될까? (0) | 2025.02.13 |
[Spring] Spring에서 @RequestBody를 사용할 때 주의해야 할 점 (0) | 2025.02.04 |
[Spring] queryForObject() vs query() (0) | 2025.02.03 |
[TIL] 네트워크, HTTP와 HTTP의 특징 (0) | 2025.01.22 |