아카이브

[스프링 데이터 JPA] 스프링 데이터 JPA 10. 트랜잭션 본문

Spring/스프링 데이터 JPA

[스프링 데이터 JPA] 스프링 데이터 JPA 10. 트랜잭션

주멘이 2021. 1. 17. 13:21

스프링 데이터 JPA가 제공하는 Repository의 모든 메서드에는 기본적으로 @Transaction이 적용되어 있습니다.

스프링 프레임워크가 제공하는 트랜잭션 기능과 거의 흡사하여 JPA 특화라고 보기는 어렵다

스프링 @Transactional

 

Transactional (Spring Framework 5.3.3 API)

Defines zero (0) or more exception names (for exceptions which must be a subclass of Throwable), indicating which exception types must cause a transaction rollback. This can be a substring of a fully qualified class name, with no wildcard support at presen

docs.spring.io

  • 클래스, 인터페이스, 메소드에 사용할 수 있으며, 메서드에 가장 가까운 애노테이션이 우선순위가 높다

JPA 구현체로 Hibernate를 사용할 때 트랜잭션을 readOnly를 사용하면 좋은 점

  • Flush 모드를 NEVER로 설정하여, Dirty checking(상태 변화 감지)을 하지 않도록 한다.
  • 데이터 변경이 일어나지 않기에 DB Sync를 하지 않는다.
  • 데이터를 많이 가져오는 경우에 Dirty checking을 끄면 성능 향상
  • 트랜잭션 커밋 시점에 Flush 하지 않으므로 이로 인한 Dirty checking 비용이 들지 않고 CPU 자원 절약

@Service에 @Transactional 설정을 통해 하나의 트랜잭션으로 묶을 수 있다.

@Service
class UserManagementImpl implements UserManagement {

  private final UserRepository userRepository;
  private final RoleRepository roleRepository;

  @Autowired
  public UserManagementImpl(UserRepository userRepository,
    RoleRepository roleRepository) {
    this.userRepository = userRepository;
    this.roleRepository = roleRepository;
  }
  
  /* 여러 Repository를 사용하는 곳을 하나의 트랜잭션으로 묶는다 */

  @Transactional
  public void addRoleToAllUsers(String roleName) {

    Role role = roleRepository.findByName(roleName);

    for (User user : userRepository.findAll()) {
      user.addRole(role);
      userRepository.save(user);
    }
}