1. 기본 트랜잭션 설정
SimpleJpaRepository
- CrudRepository의 실제 구현체
- CRUD 메서드의 트랜잭션 설정 담당
- 읽기 작업의 경우, 트랜잭션 설정의 readOnly 플래그는 true로 설정됩니다.
- 그 외의 모든 작업은 @Transactional로 설정됩니다. (기본 트랜잭션 설정이 적용되도록)
2. 트랜잭션 설정 커스터마이징
특정 저장소 메서드의 트랜잭션 설정 조정
- Method Override (+@Transactional 설정)
더보기
public interface UserRepository extends CrudRepository<User, Long> {
@Override
@Transactional(timeout = 10)
public List<User> findAll();
// Further query method declarations
}
- findAll() 메서드는 10초의 타임아웃을 갖고 readOnly 플래그 없이 실행됩니다.
3. 트랜잭션 행동 변경
파사드 구현
- 복잡한 여러 서비스/레포지토리 호출을 하나로 묶는 외부 서비스 계층
- 트랜잭션 경계를 깔끔하게 정의하기 위해 사용
코드) 파사드 활성화
더보기
@Configuration
@EnableTransactionManagement
public class AppConfig {
@Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory emf) {
return new JpaTransactionManager(emf);
}
}
- Spring 트랜잭션 AOP 활성화
- @Transactional 같은 트랜잭션 어노테이션이 제대로 동작하려면 켜줘야 함
코드) 트랜잭션 경계 설정
더보기
@Service
public class UserManagementImpl implements UserManagement {
private final UserRepository userRepository;
private final RoleRepository roleRepository;
public UserManagementImpl(UserRepository userRepository, RoleRepository roleRepository) {
this.userRepository = userRepository;
this.roleRepository = roleRepository;
}
@Transactional
public void addRoleToAllUsers(String roleName) {
Role role = roleRepository.findByName(roleName);
for (User user : userRepository.findAll()) {
user.addRole(role);
userRepository.save(user);
}
}
}
- addRoleToAllUsers(...): 해당 트랜잭션 경계 안에서 메서드들이 하나의 트랜잭션으로 실행됨
- 실제로 사용될 트랜잭션이 설정됩니다. (저장소에서의 트랜잭션 설정은 무시)
JPA와의 일관성
- 영속성 컨텍스트를 통해 엔터티의 상태 변화를 자동으로 추적
dirty check
- 엔터티는 자동으로 변경사항이 감지됨
- 트랜잭션이 커밋될 때 자동으로 엔티티의 변경 상태를 데이터베이스에 반영함
- save 호출 필요 X (일관성을 위해 save()를 호출하는 것이 좋음)
4. Transactional query methods
트랜잭션 기본 설정
- 선언된 쿼리 메서드는 트랜잭션 설정 X
- 이러한 메서드들을 트랜잭셔널하게 실행하려면, 정의한 저장소 인터페이스에 @Transactional 어노테이션 사용
readOnly 플래그
- 읽기 전용 쿼리에 대한 트랜잭션
- 최적화 효과
- JDBC 드라이버에 "읽기 전용" 힌트 전달 (조작 쿼리 검사 ❌)
- flushMode=NEVER (영속성 컨텍스트의 변경사항을 DB에 반영 ❌)
예제) readOnly
더보기
@Transactional(readOnly = true)
interface UserRepository extends JpaRepository<User, Long> {
List<User> findByLastname(String lastname);
@Modifying
@Transactional
@Query("delete from User u where u.active = false")
void deleteInactiveUsers();
}
- 클래스 레벨 트랜잭션
- @Transactional(readOnly = true)
- 대부분의 쿼리 메서드가 데이터를 읽기만 하도록 설정
- deleteInactiveUsers() 메서드
- 데이터를 수정하는 메서드입니다.
- @Modifying 어노테이션 사용
- 트랜잭션 설정을 재정의하여 readOnly 플래그를 false로 설정
출처
'Spring > Spring Data JPA' 카테고리의 다른 글
[자바 ORM 표준 JPA 프로그래밍] 3. 영속성 관리 (0) | 2023.11.28 |
---|---|
[자바 ORM 표준 JPA 프로그래밍] 2. JPA 시작 (0) | 2023.11.28 |
[자바 ORM 표준 JPA 프로그래밍] 1. JPA 소개 (0) | 2023.11.28 |
[Spring Data JPA] 2-1. Configuration (0) | 2023.10.18 |
[Spring Data JPA] 1. Core concepts (1) | 2023.10.17 |