읽기 전용 트랜잭션을 설정하면 JPA가 데이터를 변경하지 않도록 최적화합니다.
@Transactional(readOnly = true)
public User getUser(Long id) {
return userRepository.findById(id).orElseThrow();
}
readOnly = true를 사용하면 변경 감지(Dirty Checking) 기능이 비활성화됨 → 성능 최적화트랜잭션이 존재할 때, 새로운 트랜잭션을 어떻게 처리할지를 결정합니다.
| 전파 옵션 | 설명 |
|---|---|
REQUIRED (기본값) |
기존 트랜잭션이 있으면 그대로 사용, 없으면 새로 생성 |
REQUIRES_NEW |
기존 트랜잭션을 무시하고 새 트랜잭션 생성 |
MANDATORY |
반드시 기존 트랜잭션이 있어야 함 (없으면 예외 발생) |
SUPPORTS |
트랜잭션이 있으면 참여, 없으면 트랜잭션 없이 실행 |
NOT_SUPPORTED |
트랜잭션 없이 실행 (기존 트랜잭션이 있으면 일시 중지) |
NEVER |
트랜잭션이 있으면 예외 발생 |
REQUIRES_NEW 예제기존 트랜잭션과 별도로 실행해야 하는 경우 REQUIRES_NEW를 사용하면, 한 트랜잭션이 롤백되어도 다른 트랜잭션은 유지됩니다.
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
@Autowired
private LogService logService;
@Transactional
public void createUser(String name) {
userRepository.save(new User(name));
logService.logTransaction(name); // 별도 트랜잭션 실행
if (name.equals("error")) {
throw new RuntimeException("강제 예외 발생");
}
}
}
@Service
public class LogService {
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void logTransaction(String message) {
System.out.println("로그 저장: " + message);
// 예외가 발생해도 기존 트랜잭션과 독립적
}
}
createUser("John") → 정상 실행 (User 저장 + 로그 저장)createUser("error") → User 저장 실패 (Rollback), 로그는 유지 (Commit됨)여러 트랜잭션이 동시에 실행될 때, 데이터 정합성을 유지하기 위한 설정입니다.