블로그를 변경하였습니다.

해당 블로그는 더 이상 추가 포스팅 없을 예정입니다.

👉 새 블로그 방문하기


[Spring] Transaction

2021. 6. 21. 11:28
728x90
반응형

Transaction

트랜잭션(Transaction, 트랜잭션)이란, 데이터베이스의 상태를 변화시키기 해서 수행하는 작업의 단위를 뜻한다.

 

간단하게 말해서 아래의 질의어(SQL)를 이용하여 데이터베이스를 접근 하는 것을 의미한다.

  1. SELECT
  2. INSERT
  3. DELETE
  4. UPDATE

 

작업단위는 많은 질의어 명령문들을 사람이 정하는 기준에 따라 정하는 것을 의미한다.

 

게시판 사용자는 게시글을 작성하고, 올리기 버튼을 누른다. 그 후에 다시 게시판에 돌아왔을때, 

 

게시판은 자신의 글이 포함된 업데이트된 게시판을 보게 된다.

 

이러한 상황을 데이터베이스 작업으로 옮기면, 사용자가 올리기 버튼을 눌렀을 시, Insert 문을 사용하여

 

사용자가 입력한 게시글의 데이터를 옮긴다. 그 후에, 게시판을 구성할 데이터를 다시 Select 하여 최신 정보로

 

유지한다. 여기서 작업의 단위는 insert문과 select문 둘다 를 합친것이다. 이러한 작업단위를 하나의 트랜잭션이라 한다.

 

 

트랜잭션의 특징

 트랜잭션의 특징은 크게 4가지로 구분

  1. 원자성 (Atomicity)
  2. 일관성 (Consistency)
  3. 독립성 (Isolation)
  4. 지속성 (Durability)

 

 첫번째로, 원자성은 트랜잭션이 데이터베이스에 모두 반영되던가, 아니면 전혀 반영되지 않아야 한다는 것이다.  트랜잭션은 사람이 설계한 논리적인 작업 단위로서, 일처리는 작업단위 별로 이루어 져야 사람이 다루는데 무리가 없다.

 

만약 트랜잭션 단위로 데이터가 처리되지 않는다면, 설계한 사람은 데이터 처리 시스템을 이해하기 힘들 뿐만 아니라, 오작동 했을시 원인을 찾기가 매우 힘들어질것이다.

 

 두번째로, 일관성은 트랜잭션의 작업 처리 결과가 항상 일관성이 있어야 한다는 것이다. 

 

트랜잭션이 진행되는 동안에 데이터베이스가 변경 되더라도 업데이트된 데이터베이스로 트랜잭션이 진행되는것이 아니라,

 

처음에 트랜잭션을 진행 하기 위해 참조한 데이터베이스로 진행된다. 이렇게 함으로써 각 사용자는 일관성 있는 데이터를 볼 수 있는 것이다.

 

 세번째로, 독립성은 둘 이상의 트랜잭션이 동시에 실행되고 있을 경우 어떤 하나의 트랜잭션이라도, 다른 트랜잭션의 연산에 끼어들 수 없다는 점을 가리킨다.

 

하나의 특정 트랜잭션이 완료될때까지, 다른 트랜잭션이 특정 트랜잭션의 결과를 참조할 수 없다.

 

 네번째로, 지속성은 트랜잭션이 성공적으로 완료됬을 경우, 결과는 영구적으로 반영되어야 한다는 점이다.

 

 

트랜잭션의 Commit, Rollback 연산

Commit이란 하나의 트랜잭션이 성공적으로 끝났고, 데이터베이스가 일관성있는 상태에 있을 때, 하나의 트랜잭션이 끝났다라는 것을

 

알려주기위해 사용하는 연산이다. 이 연산을 사용하면 수행했던 트랜잭션이 로그에 저장되며, 후에 Rollback 연산을 수행했었던 트랜잭션단위로 하는것을 도와준다.

 

Rollback이란 하나의 트랜잭션 처리가 비정상적으로 종료되어 트랜잭션의 원자성이 깨진경우, 트랜잭션을 처음부터 다시 시작하거나, 트랜잭션의 부분적으로만 연산된 결과를 다시 취소시킨다.

 

후에 사용자가 트랜잭션 처리된 단위대로 Rollback을 진행할 수도 있다.

 


Spring에서의 트랜잭션 처리 방법 

=> 컨테이터가 자동으로 처리하도록 설정

  1. AOP필요
  2. applicationContext.xml 에 트랜잭션 관련 tx네임스페이스 필요 
  3. 반드시 xml기반으로 설정(어노테이션 불가능
  4. <aop:advisor~~></aop:advisor>를 이용하여 설정.(<aop:aspect>사용불가)

 

트랜잭션을 사용하기 위해서는 Namespace에 tx 체크

 

**  트랜잭션 관리자

-> 모든 트랜잭션 관리자는 PlatformTransactionManaer를 구현 받는다.

public interface PlatformTransactionManager {
	
	TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;
	
	void commit(TransactionStatus status) throws TransactionException;
	
	void rollback(TransactionStatus status) throws TransactionException;
}

 

이번 실습에서 사용할 spring이 제공하는 클래스 중 DataSourceTransactionManager 클래스도PlatformTransactionManaer을 구현 받는다.

 

**** 트랜잰셕 등록 : 어떻게 연동되는 지에 따라 트랜잭션 관리 클래스는 변경됨
	현재 사용하고 있는 연동방식은 DataSource를 이용하기 때문에 스프링이 제공하는
	DataSourceTransactionManager 클래스 사용
	mybatis와 JPA연동방식에서는 해당 트랜잭션 관리 클래스가 다르다.


<!-- Transaction Registration -->
	<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	
<!-- Transaction Configuration -->
	<tx:advice id="txAdvice" transaction-manager="txManager">
		<tx:attributes>
			<tx:method name="get*" read-only="true"/>
            => get으로 시작하는 메서드를 트랜젝션관리 대상으로 설정
			<tx:method name="*"/>
            => 모든 메서드를 트랜젝션 관리 대상으로 설정
		</tx:attributes>
	</tx:advice>
	
<!-- Transaction Advisor Configuration -->
	<aop:config>
		<aop:pointcut expression="execution(* com.jdh.spring..*Impl.*(..))" id="txPointcut"/>
		<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
	</aop:config>

<bean id="객체명" class="트랜잭션관리 클래스"> 통하여 등록
DB접속이 필요하기 때문에 내부에 <property>태그를 이용하여 어떤 접속방식을 사용하는 전달

 

 

<tx:method> 태그의 속성

    name => 트랜잭션 전용 메서드 지정
    read-only="true" => 읽기 전용 여부 지정( 기본 false) true 설정시 해당 메서드는 트랜잭션 관리 대상에서 제외
    no-rollback-for =>  트랜잭션을 롤백하지 않을 예외 지정
    rollback-for => 트랜잭션을 롤밸할 예외 지정

 

트랜잭션 흐름)

게시판에서 글 작성을 통하여 새로운 글이 들어올 경우 insertBoard()라는(글작성메서드) 비즈니스 로직이 수행된다.

이때 로직을 처리하는 과정에서 문제가 발생하면 txAdvice로 등록한 어드바이스가 동작하여

참조하는 txManager의 rollback() 메서드를 호출하게되고, 만약 문제가 없다면 commit()메서드 호출

 

테스트)

@Service("boardService")
public class BoardServiceImpl implements BoardService {
	
	@Autowired
	private BoardDAOSpring boardDAO;

	public BoardServiceImpl() {
	}

	@Override
	public void insertBoard(BoardVO vo) {
		
 		this.boardDAO.insertBoard(vo);	// 글번호가 100인 게시글 등록
		this.boardDAO.insertBoard(vo);	// 예외발생

값 확인을 위하여 기존에 게시글 번호 자동증가 쿼리를 지우고 100으로 수정(게시글 번호는 PK지정)

 

insertBoard(vo) 가 실행되고, 처음 실행됐을때는 정상적으로 글이 추가가 된다.(이때 commit() 메서드 호출)

하지만 두번째 실행된 insertBoard(vo) 는 예외가 발생한다.(게시글이 100번으로 중복) (이때 rollback() )

 

 


728x90
반응형

'개발노트 > Spring' 카테고리의 다른 글

[Spring Boot] Thymeleaf  (0) 2021.07.09
[Spring] JPA 관련 레퍼런스  (0) 2021.07.05
[Spring] JDBC  (0) 2021.06.18
[Spring] IoC(inversion of Control)  (0) 2021.06.18
[Spring] AOP(Aspect Oriented Programming)  (0) 2021.06.17

BELATED ARTICLES

more