2019년 1월 13일 일요일

스프링에서 선언식 트랜잭션 간단하게 실습해보기

트랜잭션이란??

정보처리기사에 정말 많이 나오는 개념으로 all or nothing 이라고 생각하면 된다.
'모두 처리 아니면 모두 X'
예를 들면, 트랜잭션이 적용된 어떠한 행동이 3가지의 insert , update, insert의 쿼리를 수행하는 행동일 때,
insert 성공
update 성공
insert 실패
가 되었을 때 앞의 insert와 update 쿼리가 성공이 되었을 지라도 마지막 insert가 실패되었기 때문에 모두 롤백이 되어야하는 개념이다.
스프링에서 트랜잭션은 선언식 트랜잭션과 프로그램에 의한 트랜잭션을 통해 사용할 수 있는 것 같다.
선언식 트랜잭션 중 어노테이션방법을 게시판의 예제로 간단하게 살펴보자
사용자가 게시물을 클릭한다고 생각하면 다음의 순서로 진행된다. 
1. 조회수가 오른다. (update)
2. 게시물의 데이터를 가져온다. (select)
만약 이때 2. select 과정에서 오류가 발생한다고 가정한다면, 게시물의 데이터를 못가져왔으므로 조회가 되지않는다. 그렇다면 조회수도 오르지 말아야한다.
(예시가 좀 이상하다. 적절한 예시를 찾아서 수정해야할듯...)
이 행동에 대해서 트랜잭션을 적용해보겠다.

root-context.xml
...

    <!-- transactionManager -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

...
servlet-context.xml
...

<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>

...
serviceImpl
package com.wpp.service;
...
import org.springframework.transaction.annotation.Transactional;
...

@Service
public class BoardServiceImpl implements BoardService{
...


@Transactional
public Object read(int bnum) throws Exception {
    Object object = null;

    //조회수 올리기
    boardDao.uphit(bnum);

    //게시물 내용
    object = boardDao.read(bnum);

    //트랜잭션 테스트를 위한 Exception 발생
    if( object == null) {
        throw new RuntimeException();
    }

    return object;
}


...
}
아까 만든 가정대로 테스트를 하기위해
다음과 같이 object가 null이면 RuntimeException 을 발생시켜보았다.
breakpoint를 잡고 object = freeboardDao.read(bnum); 부분에 bum의 값을 DB에 없는 값을 줘서 object를 null이 나오도록 하였다.
@Transactional 어노테이션이 없을 때는 해당 Exception이 발생하더라도 그 전의 조회수가 올라가는 것을 볼 수 있지만, 어노테이션을 추가한 후에는 조회수 부분이 rollback 된 것을 볼 수 있다.

@Transactional 에는 다양한 속성을 지정해줄 수 있다.
ex_) @Transactional(isolation=Isolation.DEFAULT, timeout=10)
- 격리레벨 : 데이터에 대한 격리
  - ex_) 커밋된 데이터 읽기 허용, 커밋되지 않는 데이터 읽기 허용 등)
- 전파 : 트랜잭션 중 다른 트랜잭션 호출할 때의 경우
  - ex_) 기존에 실행되고 있는 트랜잭션이 있으면 참여 아니면 새로 생성, 무조건 트랜잭션 새로 생성
- readonly : 트랜잭션을 읽기전용으로 적용
  - ex_) 쓰기작업 발생 시 예외발생(기본설정은 false)
- rollbackFor : 특정 예외가 발생할 경우 롤백 처리 설정
  - ex_) : 스프링의 데이터엑세스 예외는 RuntimeException 이므로, 런타임예외만 롤백대상이므로 다른예외도 추가하는 방식...인가????
- timeout : timeout발생 시 롤백 처리(초단위같음)
  - ex_) : 지정된 시간안에 수행이 되지 않으면 롤백

어노테이션 외에도 aop를 이용해 service단의 모든 메소드에 트랜잭션을 적용시킬 수 있다.

게시판에 트랜잭션을 적용하려고 다시 소스를 보았는데.....
정말 개판이다..

물론 이 때는 게시판을 만들어보는 것에 목적으로 두고 생성하였지만,
참...ㅋㅋㅋ 이 구조는 왜 이런식이며...service단은 그냥 쿼리를 호출하는 거랑 뭐가 다르게 만들어졌으며..

너무 못짰다. 이게 뭐야ㅠㅠㅠㅠㅠㅠㅠㅠ
얘를 개선할 수 있을까?
todo
aop 예제도 해보자.

댓글 없음:

댓글 쓰기