1. 기본 트랜잭션 설정
CrudRepository 메서드
- SimpleJpaRepository로부터 트랜잭션 설정을 상속받습니다.
- 읽기 작업의 경우, 트랜잭션 설정의 readOnly 플래그는 true로 설정됩니다.
- 그 외의 모든 작업은 @Transactional로 설정됩니다. (기본 트랜잭션 설정이 적용되도록)
2. 트랜잭션 설정 커스터마이징
특정 저장소 메서드의 트랜잭션 설정 조정
- Method Override (+@Transactional 설정)
- findAll() 메서드는 10초의 타임아웃을 갖고 readOnly 플래그 없이 실행됩니다.
public interface UserRepository extends CrudRepository<User, Long> {
@Override
@Transactional(timeout = 10)
public List<User> findAll();
// Further query method declarations
}
3. 트랜잭션 행동 변경
파사드 구현
- 트랜잭션 경계를 정의하기 위해 서비스 또는 파사드 구현 방법이 있습니다. (여러 저장소 사용 고려)
파사드 활성화
- <tx:annotation-driven /> 활성화
- @EnableTransactionManagement
@Configuration
@EnableTransactionManagement
public class AppConfig {
@Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory emf) {
return new JpaTransactionManager(emf);
}
}
외부 트랜잭션 설정
@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 드라이버에 힌트로 전달 (성능 최적화용)
- 조작 쿼리가 발생하지 않도록 하는 검사 X
최적화 수행 (기본 JPA 제공자에 한함)
- flushMode=NEVER
- 성능 향상 (큰 객체 트리에서)
@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 |