기본적으로 트랜잭션 안에서 데이터를 변경하는 것은 @Transactional이 꼭 있어야 한다.
@Transactional은 두 개가 있다.
import jakarta.transaction.Transactional; //이전 javaX. 지금은 jakarta
import org.springframework.transaction.annotation.Transactional; // 스프링
jakarta(이전 javax)에서 제공하는 것과 스프링에서 제공하는 것.
이미 스프링을 사용하고 있으므로 스프링에 Dependency한 로직이 많이 들어 있음으로 스프링에서 제공하는 @Transactional를 사용하는게 낫다. 더 많은 기능을 제공한다.
이 트랜젝션 어노테이션을 클래스 레벨에서 주는 방법이 있고, 메서드 레벨에서 주는 방법이 있다.
- 클래스 레벨에서 @Transactional 주는 방법
@Service
@Transactional //클래스 레벨에서 주는 방법
public class MemberService {
클래스 레벨에서 @Transactional를 사용하면 public 메서드들은 기본적으로 트랜젝션이 걸려 들어간다.
- 메서드 레벨에서 @Transactional 주는 방법
@Service
public class MemberService {
@Autowired
private MemberRepository memberRepository;
//회원 가입
@Transactional(readOnly = false) //readOnly 기본값은 false이다.
public Long join(Member member) {
validateDuplicateMember (member); //중복 회원 검증
memberRepository.save(member);
return member.getId();
}
...
//회원 전체 조회
@Transactional(readOnly = true)
public List<Member> findMembers() {
return memberRepository.findAll();
}
//개별 회원 조회
@Transactional(readOnly = true)
public Member findOne(Long memberId) {
return memberRepository.findOne(memberId);
}
...
}
JPA에서 조회하는데 @Transactional(readOnly = true)옵션을 주면, JPA가 조회하는 곳에서는 성능을 좀 더 최적화 한다.
예를 들면, 영속성 컨텍스트를 플러시 안하거나 더티체킹을 안하는 것에 대한 이점도 있고, 추가로 데이터 베이스에 따라서는 읽기 전용 트랜젝션이라고 하면 DB에게 읽기 전용이기 때문에 리소스를 많이 쓰지 말고 단순하게 읽기로 DB가 읽도록 하는 것도 있다. (DB 드라이버마다 확인이 필요함.)
분명한 것은 읽기 전용인 메서드에는 readOnly = true 옵션을 넣어주어야 한다.
그리고, 읽기가 아닌 쓰기 메서드에 readOnly = true를 넣으면 안된다. 데이터 변경이 안되기 때문이다.
클래스 레벨에서 주는 방법으로 하면, 읽기 메서드가 많은 경우 중복 기록을 피할 수 있다.
@Service
@Transactional(readOnly = true)
public class MemberService {
@Autowired
private MemberRepository memberRepository;
//회원 가입
@Transactional //readOnly 기본값은 false이다!
public Long join(Member member) {
validateDuplicateMember (member); //중복 회원 검즘
memberRepository.save(member);
return member.getId();
}
...
//회원 전체 조회
public List<Member> findMembers() {
return memberRepository.findAll();
}
//개별 회원 조회
public Member findOne(Long memberId) {
return memberRepository.findOne(memberId);
}
...
}
읽기가 많은 경우에는 이렇게 세팅해서 사용하는 것이 좋겠다.
쓰기가 많은 경우라면 반대로 해당 경우에 맞게 적용하자.
'스프링 부트' 카테고리의 다른 글
JUnit4 스프링 부트 테스트 ① (0) | 2025.02.18 |
---|---|
@Autowired 어노테이션을 통한 인젝션(Injection) 방법들 (0) | 2025.02.18 |
JPA @GeneratedValue (0) | 2025.02.18 |
[error] fatal: 관계 없는 커밋 내역의 병합을 거부합니다 (0) | 2025.02.14 |
GitHub 원격 저장소의 모든 브랜치 가져오기 (0) | 2025.02.14 |