트랜잭션?
하나의 작업으로 취급하기 위해 여러 작업을 하나로 묶은 것
포인트컷?
일종의 필터 역할로, 어떤 메소드에 어드바이스를 적용할지 결정하는 기준을 정의하는 역할을 한다.
어드바이스?
어드바이스는 핵심 비즈니스 로직에 적용되는 부가 기능 사항을 정의하여 등록한 빈 객체
포인트컷과 트랜잭션 속성을 이용해 트랜잭션을 일괄적으로 적용하는 방식은 세밀하게 튜닝된 트랜잭션 속성의 경우 포인트컷과 트랜잭션 속성 사용으로는 적합하지 않다.
타겟 메소드 (Target Method):
@Transactional 어노테이션을 사용하여 트랜잭션을 적용할 메소드를 지정한다.
이 메소드에서 예외가 발생하면 예외 처리와 롤백을 관리할 수 있다.
타겟 클래스 (Target Class):
@Transactional 어노테이션을 사용하여 트랜잭션을 적용하는 대상 클래스를 지정한다.
트랜잭션을 관리하고자 하는 비즈니스 로직이 포함된 클래스를 의미한다.
선언 메소드 (Advisor Method):
@Transactional 어노테이션의 fallback 옵션에서 지정한 메소드를 호출하는 역할을 수행한다.
예외가 발생한 경우에 호출되며, 해당 메소드가 적절한 처리를 수행할 수 있도록 한다.
선언 타입 (Advisor Type):
선언 메소드가 속한 클래스의 타입을 지정한다.
@Aspect 어노테이션을 사용하여 Aspect 클래스를 생성하고, 해당 클래스 내에 선언 메소드를 정의하여 예외 상황에 대한 처리를 구현한다.
[1] // 선언 타입
public interface Service {
[2] // 선언 메소드
void method1();
[3]
void method2();
}
[4] // 타겟 클래스
public class Servicelmpl implements Service {
[5] // 타겟 메소드
public void method1() (
[6]
public void method2() {
}
@Transactional
public interface UserService {
void add(User user);
void deleteAll();
void update(User user1);
void upgradeLevels();
// 메소드 레벨에 @Trasactional이 없으므로 타입레벨에 부여된 디폴트 속성이 부여된다.
@Transactional(readOnly = true)
User get(String id);
@Transactional(readOnly = true)
List<User> getAll();
// 메소드 레벨에 부여됐기 때문에 메소드 마다 반복된다.
}
트랜잭션 전파속성?
- 트랜잭션 전파 속성은 여러 트랜잭션 메소드들이 서로 상호작용할 때 어떻게 동작할지를 정의하는 설정
- 트랜잭션 메소드에서 다른 트랜잭션 메소드를 호출할 때, 어떤 방식으로 트랜잭션이 전파되고 관리될지 결정
REQUIRED로 전파속성 지정
add 메소드에 트랜잭션 전파속성을 지정
선언적 트랜잭션 : AOP를 이용해 코드 외부에서 트랜잭션 기능을 부여해주는 방법
프로그램에 의한 트랜잭션 : TransactionTemplate나 개별 데이터 트랜잭션 API를 사용해 직접 코드 안에서 사용하는 방법
특수한 상황을 제외하고, 선언적 트랜잭션 방법을 사용하는 것을 추천함
트랜잭션 동기화 기술은 같은 DB Connection을 공유하는 특성을 이용하여 트랜잭션 전파 속성에 따라 참여할 수 있도록 한다.
트랜잭션 매니저를 사용해 테스트 데이터를 조작하는 등의 작업을 수행할 수 있다.
트랜잭션 매니저를 사용하면 테스트에서 트랜잭션의 시작, 커밋, 롤백 등을 조작하여 테스트 환경을 조정할 수 있다.
public class UserServiceTest {
...
@Test
public void transactionSync(){
DefaultTransactionDefinition txDefinition = new DefaultTransactionDefinition();
TransactionStatus txStatus = transactionManager.getTransaction(txDefinition);
userService.deleteAll();
userService.add(users.get(0));
userService.add(users.get(1));
transactionManager.commit(txStatus);
}
}
실행되는 트랜잭션은 3개
스프링 트랜잭션 추상화가 제공하는 트랜잭션 동기화 기술과 트랜잭션 전파 속성 덕에 테스트도 트랜잭션으로 묶을 수 있다.
이를 통해 효과적인 테스트를 만들 수 있다.
public class UserServiceTest {
...
@Test
public void transactionSync(){
userDao.deleteAll(); // 초기화
assertThat(userDao.getCount(), is(0));
DefaultTransactionDefinition txDefinition = new DefaultTransactionDefinition();
TransactionStatus txStatus = transactionManager.getTransaction(txDefinition);
userService.add(users.get(0));
userService.add(users.get(1));
assertThat(userDao.getCount(), is(2));
transactionManager.rollback(txStatus);
assertThat(userDao.getCount(), is(0));
}
}
롤백이 잘 되는 지 테스트 할 수 있다.
테스트가 끝나면 롤백 하는 테스트
public class UserServiceTest {
...
@Test
public void transactionSync() {
DefaultTransactionDefinition txDefinition = new DefaultTransactionDefinition();
TransactionStatus txStatus = transactionManager.getTransaction(txDefinition);
try {
userService.deleteAll();
userService.add(users.get(0));
userService.add(users.get(1));
} finally {
transactionManager.rollback(txStatus);
}
}
}
스프링은 어노테이션을 통해 테스트를 편리하게 만들 수 있는 여러 기능을 제공한다.
@Transactional
@Rollback
@TransactionConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "/applicationContext.xml")
@Transactional
@TransactionConfiguration(defaultRollback = false)
public class UserServiceTest {
@Test
@Rollback //롤백
public void add(){}
}
6.8.10 @NotTransactional과 Propagation.NEVER
@Transactional(propagation = Propagation.NEVER)
효과적인 DB 테스트
- 테스트 내에서 트랜잭션을 제어할 수 있는 네 가지 애노테이션을 활용해 편리하게 통합 테스트 코드를 만들 수 있다.
- DB가 사용되는 통합 테스트는 롤백 테스트로 만드는 것을 권장 한다.