[JPA & Hibernate] JPA Hidden Traps

원알렉스·2020년 9월 10일
0

JPA

목록 보기
16/16
post-thumbnail
post-custom-banner

1️⃣ @Transactional 낭비

아래의 메소드를 보시면 모든 것이 제대로 흘러 가는 것을 볼 수가 있습니다.

  • 데이터베이스로부터 엔티티가 반환된다.
  • 반환된 엔티티의 필드를 변경한다.
  • 조건이 맞다면 변경 사항을 데이터베이스로 업데이트 한다.
public void verifyAndUpdateUniverse(Integer universeId, UniverseDto universeDto) {
    Universe universe = universeRepository.getOne(universeId);
    universe.setUniverseName(universeDto.getUniversename());
    
    if (!universeDto.getUniverseName().equals("Invalid Universe")) {
        universeRepository.save(universe);
    }
}

하지만 @Transactional 어노테이션을 붙이면 어떻게 될까요?

@Transactional
public void verifyAndUpdateUniverse(Integer universeId, UniverseDto universeDto) {
    Universe universe = universeRepository.getOne(universeId);
    universe.setUniverseName(universeDto.getUniversename());
    
    if (!universeDto.getUniverseName().equals("Invalid Universe")) {
        universeRepository.save(universe);
    }
}

만약 @Transactional 어노테이션을 메소드나 클래스에 붙이게 되면, 모든 변경 사항들은 해당 메소드가 끝날 경우에 데이터베이스로 반영이 됩니다.

즉, 위의 코드를 보시면 if 조건문을 만족하지 않아도 해당 엔티티의 변경사항은 데이터베이스로 반영이 됩니다.

2️⃣ Rollback 불실행

위의 코드를 수정해서 if 조건문을 만족한다면 예외를 던지는 구조로 바꿔보았습니다.

@Transactional
public void verifyAndUpdateUniverse(Integer universeId, UniverseDto universeDto) {
    Universe universe = universeRepository.getOne(universeId);
    universe.setUniverseName(universeDto.getUniversename());
    
    if (!universeDto.getUniverseName().equals("Invalid Universe")) {
        throw new InvalidUniverseException();
    }
}

예외 클래스는 아래와 같습니다.

public class InvalidUniverseException extends Exception {
    ...
}

그래서 위의 코드를 실행하게 되면 예외를 던진다 하더라도 Rollback은 실행되지 않습니다. 그 이유는 Rollback은 기본적으로 Unchecked Exception에만 실행됩니다.

그래서 우리가 생각하던대로 실행되기 위해서는 @Transactional 의 파라미터로 rollbackOn 을 줘서 Rollback 을 시켜줄 Checked Exception 지정해주면 됩니다.

@Transactional(rollbackOn = InvalidUniverseException.class)
public void verifyAndUpdateUniverse(Integer universeId, UniverseDto universeDto) {
    Universe universe = universeRepository.getOne(universeId);
    universe.setUniverseName(universeDto.getUniversename());
    
    if (!universeDto.getUniverseName().equals("Invalid Universe")) {
        throw new InvalidUniverseException();
    }
}

반대로 dontRollbackOn 파라미터를 줘서 특정 Unchecked Exception 이 발생하게 되면 Rollback을 실행시키지 않도록 해줄 수도 있습니다.

profile
Alex's Develog 🤔
post-custom-banner

0개의 댓글