'트랜잭션'에 해당되는 글 1건

  1. 2018.03.07 :: Spring(스프링) Transaction(트랜잭션) 범위설정
Web/Spring 2018. 3. 7. 16:28

Spring Transaction(트랜잭션) 범위 설정하기



1.예외 상황(트랜잭션 범위설정이전)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public void insertUserTest() {
        
        UserDTO user1=new UserDTO();
        UserDTO user2=new UserDTO();
        UserDTO user3=new UserDTO();
        
        user1.setId("test@test.com");
        user1.setPw("1111");
        user1.setNickName("tester");
        user2.setId("test1@test.com");
        user2.setPw("1111");
        user2.setNickName("tester1");
        user3.setId("test@test.com");
        user3.setPw("1111");
        user3.setNickName("tester2");
        
        userService.insertUser(user1);
        userService.insertUser(user2);
        userService.insertUser(user3);
        
    }
cs

예를 들어 이런 코드가 있다고 가정해보자. 여기서 보면 user3이라는 객체의 인스턴스변수를 설정해줄때, user3.setId() 메소드 부분에 user1과 같은 id가 들어가서 duplicationkey라는 예외가 발생하여 user3은 DB에 정상적으로 데이터가 삽입되지 않을 것이다. 여기서 transaction manager를 사용한다고 가정했을 때,



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    <!-- Transaction Manager -->
    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <!-- txManager Advice -->
    <tx:advice id="txAdvice" transaction-manager="txManager">
        <tx:attributes>
            <tx:method name="get*" read-only="true"/>
            <tx:method name="*" propagation="REQUIRED"/>
        </tx:attributes>    
    </tx:advice>
    <!-- txManagerAdvice aop -->
    <aop:config>
        <aop:pointcut expression="execution(* com.web.nuri..*(..))" id="txPointCut"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
    </aop:config>
cs

위에 보이는 대로 transaction manager를 설정하면 user1, user2는 정상적으로 DB에 삽입되고 user3는 DB에 저장되지 않고 rollback 될 것이다. 즉, UserDAO(userService)의 메소드 단위로 트랜잭션이 적용되어 user3에서 예외가 발생하여도 user1,user2는 정상적으로 DB에 삽입이 되는 것이다. 본인은 트랜잭션의 범위의 설정을 메소드 단위가 아닌 내가 직접 범위를 설정하여 user3에서 예외가 발생하였다고 하면 이전의 user1,user2의 데이터도 DB에 삽입되지 않게 하고 싶은 것이다.



2.트랜잭션 범위 설정


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public class UserDAOTest {
    @Autowired
    UserService userService;
    @Autowired
    PlatformTransactionManager transactionManager;
    
    //트랜잭션 경계설정 코드
    public void insertUserTest() {
        //트랜잭션의 시작을 알린다.(트랜잭션을 얻어오는 시점이 시작)
        TransactionStatus status=this.transactionManager.getTransaction(new DefaultTransactionDefinition());
        UserDTO user1=new UserDTO();
        UserDTO user2=new UserDTO();
        UserDTO user3=new UserDTO();
        try {
            user1.setId("test@test.com");
            user1.setPw("1111");
            user1.setNickName("tester");
            user2.setId("test1@test.com");
            user2.setPw("1111");
            user2.setNickName("tester1");
            user3.setId("test@test.com");
            user3.setPw("1111");
            user3.setNickName("tester2");
        
            userService.insertUser(user1);
            userService.insertUser(user2);
            userService.insertUser(user3);
            this.transactionManager.commit(status);
        }catch (RuntimeException e) {
            // TODO: handle exception
            this.transactionManager.rollback(status);
            throw e;
        }        
    }
}
cs



여기에 적용되는 것은 스프링의 트랜잭션 서비스 추상화 기법이다. PlatformTransactionManager(트랜잭션매니저의 최상위 인터페이스) 라는 인터페이스에 각자의 DB에 해당되는 TransactionManager 클래스(여기서는 mybatis를 이용하므로 DataSourceTransactionManager가 된다)를 의존주입 해준 후에 TransactionStatus 객체를 생성해준다.( 이시점이 트랜잭션의 시작시점이 되는 것이다.)

그리고 예외없이 메소드가 잘 수행되면 transactionManager.commit(status), 예외가 발생하였다면 transactionManager.rollback(status) 메소드를 수행시킨다. 이 시점이 트랜잭션 범위의 끝지점이 되는 것이다. 이렇게 범위를 설정하게 되면 user3 객체의 삽입에서 예외가 발생하면 user1,user2의 객체는 이전에 수행됬던 것들이 모두 rollback 된다.




posted by 여성게
: