본문 바로가기

스프링

[spring] aop_트랜잭션_전파속성_동기화_11

개발시 사용자를 대량으로 등록시 allAdd에서 트랜잭션과 독립적으로 add 서비스에서 트랜잭션 발생시

대량 등록시 트랜잭션내에 개별적인(add()) 트랜잭션이 참여해야함.

스프링의 외부(대량 등록 트랜잭션)의 트랜잭션의 기능을 부여해주고 속성을 지정해주는 방법 2가지

선언적 트랜잭션(declarative transaction) : 코드에서 직접적으로 수행하지 않으며, 설정 파일아나 어노테이션을 이용해서 트랜잭션의 범위, 롤백 규칙 등을 정의하는 방식.

프로그램에 의한 트랜잭션(programmatic transaction) : 직접 코드안에서 사용하는 방법

*  물론 특별한 경우가 아니라면 선언적 방식의 트랜잭션을 사용하는 것이 바람직하다.

 

 

AOP 덕분에 프록시를 이용한 트랜잭션 부가기능을 간단하게 어플리케이션 전반에 반영할 수 있고, 위처럼 스프링의 PlatformTransactionManager 의 모든 트랜잭션 통합을 통해 선언적 트랜잭션이나 트랜잭션 전파가 가능한 것이다.

 

 

1.     Com.springsource.javax.activation : Spring java-mail

2.     Com.springsource.javax.mail : Spring java-mail

3.     Com.springsource.org.aopalliance : Spring ProxyFactoryBean

4.     Com.springsource.org.aspectj.tools : AspectJExpressionPointcut 포인트컷 표현식 지원

5.     Com.springsource.junit : junit

6.     Commons-logging : Spring-context가 사용

7.     Mail : java-mail

8.     Mockito : 목 프레임워크 중 Mockito

9.     Mysql-connector : Mysql JDBC

10.   Org.springframework.context.support : Spring java-mail

11.   Spring-aop : 스프링 기능 자체의 aop, Spring ProxyFactoryBean

12.   Spring-bean : 스프링 빈을 활용하는 경우 필요. 스프링의 XML 설정파일과 자바 애노테이션을 파싱 하는데 필요한 클래스 포함

13.   Spring-context : 스프링 코어를 확장한 많은 클래스가 들어 있는데 모든 클래스는 EJB, JNDI(Java Naming Directory Interface), JMX용 클래스와 연동하는데 applicationcontext기능을 사용해야 하며 스프링 리모팅 클래스, 동적 스크립팅 언어(제이루비, 그루비등)와 연동하는 클래스, 빈 유효성검증(JSR-303) API, 스케줄링을 하는 클래스도 포함되어 있다.

14.   Spring-core : 모든 스프링 모듈에서 필요한 모듈. 다른 스프링 모듈에서 사용하는 공통 클래스가 포함됨.

15.   Spring-expression : 스프링 표현언어(SpEL) 지원 클래스 포함.

16.   Spring-jdbc : 스프링이 지원하는 jdbc.

17.   Spring-test.jar

-       @RunWith : Junit 프레임워크의 테스트 실행방법을 확장시 사용.

-       SpringJUnit4ClassRunner : 어플리케이션컨텍스트를 만들고 관리하는 확장 클래스

-       @ContextConfiguration(경로) : 자동으로 만들어줄 어플리케이션 컨텍스트 설정파일

18.  Spring-tx : DuplicateKeyException.class 파일 존재 및 스프링 트랜잭션

 

 

레벨의 역할은 레벨에게 위임(다음레벨 셋팅 등) 서비스의 분기처리가 작아짐

 

 

유저의 역할은 유저에게 위임(레벨셋팅)

 

JDBC, Hibernate, JDO, JPA 등의 DataAccess API를 원활히 바꿔치기 하기 위한 인터페이스

 

JDBC Dao 구현 스프링의 JdbcTemplate 사용으로 전략영역만 구현하고 템플릿 영역은 스프링이 구현함으로써 유지보수 용이

 

25. transactionManager를 빈으로 등록함으로써 <프로그램에 의한 트랜잭션(programmatic transaction) : 직접 코드안에서 사용하는 방법> 처리 가능. 어노테이션으로 소스상에 주입하여 활용

26. 어노테이션 트랜잭션 사용으로 주석처리.

39. tx:annotation-driven 설정으로 어노테이션 트랜잭션 활용

 

 

계속 메일 보내는 테스트의 진행을 막기 위한 테스트 스텁 오브젝트 구현

 

원래는 부가기능 트랜잭션 Advice를 구현해야 했지만, 스프링의 TransactionInterceptor 사용으로 위와 동일한 기능의 어드바이스가 탑재되어 있어 안씀.

 

 

트랜잭션 어노테이션 활용

인터페이스에 어노테이션을 적용하는 이유

하나의 설정으로 UserServiceImple, TestUserService 양쪽에 트랜잭션 적용이 될 수 있고, 인터페이스 프록시를 사용하는 경우 인터페이스에 적용하는 것이 대부분 옳다.

*  get으로 시작하지 않는 메소드는 디폴트 속성, get으로 시작하는 설정은 읽기 전용 속성 부여

 

 

타겟 구현. 스프링의 프록시 활용으로 타겟들에게는 트랜잭션 로직이 필요없음. 중복제거

 

 

51. 위와같이 적용하면 각각의 트랜잭션을 타게 된다.(3개의 트랜잭션을 통합하는 법)

* 3개의 트랜잭션은 REQUIRED 전파 속성으로 3개의 메소드를 실행하기 전에 트랜잭션이 시작되게 하면 된다.

> UserService새로운 메소드를 만들고 그 안에 deleteAll(), add()를 호출한다면 물론 가능하다.

> 위처럼 메소드를 추가하지 않고도 테스트 코드만으로 세 메소드의 트랜잭션을 통합하는 방법이 있다.

59. 목오브젝트를 통한 검증

 

 

 

트랜잭션 매니저를 이용해 트랜잭션을 미리 시작하게 만드는 테스트

선언적 트랜잭션(declarative transaction) : 코드에서 직접적으로 수행하지 않으며, 설정 파일아나 어노테이션을 이용해서 트랜잭션의 범위, 롤백 규칙 등을 정의하는 방식

54. new DefaultTransactionDefinition() 을 활용하여 트랜잭션 전파속성을 기본값으로 설정.

55. getTransaction(txDefinition) : 트랜잭션 매니저에게 트랜잭션을 요청. 기존에 시작된 트랜잭션이 없으므로 새로운 트랜잭션을 시작시키고 트랜잭션 정보를 받음. 동시에 만들어진 트랜잭션을 다른 곳에서도 사용할 수 있도록 동기화 처리.

58~61. 앞서 만들어진 트랜잭션에 모두 참여하게 되어 트랜잭션 처리가 된다.

 

트랜잭션 동기화 검증

Connection is read-only : 읽기전용 트랜잭션에 대해 쓰기 작업을 했을 때 발생하는 예외. 이렇게 함으로써 먼저 시작한 트랜잭션에 deleAll() 메소드가 참여하고 있다고 확신을 얻을 수 있다.

 

JdbcTemplate는 트랜잭션이 시작된 것이 있으면 그 트랜잭션에 자동으로 참여하고, 없으면 트랜잭션 없이 자동커밋 모드로 JDBC 작업을 수행함. JdbcTemplate 역시 트랜잭션 전파 속성이 REQUIRED 인 것처럼 동작한다고 볼 수 있다.

 

 

트랜잭션 롤백 테스트

 

 

롤백 테스트

테스트가 끝나면 무조건 롤백해버리는 테스트를 말함.

DB데이터와 상태가 중요할 시 데이터가 바뀌면 위험할 때 유용

적절한 격리수준만 보장이 된다면 동시에 여러 개의 테스트가 진행돼도 관계없다.

>  DB에 따라서 롤백하는게 커밋보다 빠르다(MySQL). 하지만 DB의 트랜잭션 처리 방법에 따라 롤백이 커밋보다 더 많은 부하를 주는 경우도 있으니 단지 성능 때문에 롤백테스트가 낫다고는 볼 수 없다.

 

 

트랜잭션 매니저와 번거로운 코드를 사용하는 대신 간단한 어노테이션으로 테스트를 손쉽게 만들기 가능

 

트랜잭션 전파속성이 잘 적용되었는지 테스트 역시 간단한 어노테이션 설정으로 테스트 가능.

* 테스트 메소드나 클래스(Junit 테스트는 보통 클래스 단위로 실행)에 사용하는 @Transactional은 애플리케이션의 클래스에 적용할 때 디폴트 속성은 동일하다. 하지만, 테스트용 트랜잭션은 테스트가 끝나면 자동 롤백된다는 차이점이 있다.

 

 

테스트 메소드,클래스에서 기본값으로 사용되는 강제롤백을 사용하지 않으려면 위와같이 설정

기본값 : @Rollback(true)

 

 

@Transactional은 테스트 클래스에 넣어서 모든 테스트 메소드에 일괄 적용할 수 있지만

@Rollback 애노테이션은 메소드 레벨에만 적용할 수 있다. 무식하게 메소드마다 다 부여해야 할까? 그 때는 위에처럼 설정해주는 편이 좋다.

 

대부분의 테스트에서 트랜잭션이 필요하고 몇 개의 메소드에서 트랜잭션이 필요없는 경우 위와 같이 메소드 레벨에 지정하면 트랜잭션이 시작되지 않는다.

@NotTransactional 은 스프링 3.0에서 제거 대상이 되었지만, 쓸 순 있음.