1. 정의
[예시: 은행 계좌 이체]
은행 시스템에서 A 계좌에서 B 계좌로 금액을 이체하는 과정을 예로 들어보겠습니다.
이 과정은 여러 단계로 이루어지며, 각 단계가 성공적으로 완료되어야만 전체 트랜잭션이 성공합니다.
송금 계좌(A)의 잔액 감소
수취 계좌(B)의 잔액 증가
이 두 단계 중 하나라도 실패하면 전체 트랜잭션은 롤백되어야 합니다.
예를 들어, A 계좌에서 금액을 차감했지만 B 계좌에 금액을 추가하는 데 실패하면,
A 계좌의 차감된 금액도 원래 상태로 복원되어야 합니다.
[정의]
DB 처리하는 작업 단위
DDL(Insert, Delete, Update) 실행 시 항상 commit, rollback 시행되야 트랜잭션이 종료됨
스프링에서 AOP 설정을 이용해서 트랜잭션을 처리
2. 스프링에서의 트랜잭션
트랜잭션 설정 시 aop에서 aspect 대신 advisor 사용
(이유 : 개발자가 commit과 rollback 사용 시점을 지정할 수 없기 때문)
advisor는 쿼리가 성공하면 commit, 실패하면 rollback을 시행함.
3. root-context.xml 수정
요약
이 설정을 통해, 데이터베이스 작업 중 오류가 발생했을 때 데이터의 일관성이 유지되며,
특정 메소드에 트랜잭션을 적용하거나 제외할 수 있습니다.
트랜잭션 관리를 통해 애플리케이션이 안정적이고 신뢰성 있게 동작할 수 있도록 보장합니다.
// beans 추가
<beans xmlns:tx="http://www.springframework.org/schema/tx">
// xsi:schemaLocation 추가
<xsi:schemaLocation=http://www.springframework.org/schema/tx/spring-tx.xsd">
<!--Transaction 설정-->
<!--Tansaction을 관리하는 객체를 bean으로 등록-->
//DataSourceTransactionManager는 Spring에서 제공하는 트랜잭션 매니저로,
// 데이터 소스와 연결된 트랜잭션을 관리합니다.
// dataSource를 참조하여 데이터베이스 연결을 설정합니다.
// 이를 통해 트랜잭션 매니저가 데이터베이스와의 트랜잭션을 관리할 수 있게 됩니다.
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--DML(insert, update, delete)가 종료되면 commit이나 rollback이 자동 실행되도록 설정
TransactionManager만 등록한다고 Transaction이 자동 관리되진 않고
AOP 설정을 통해서 Transaction이 공통 기능으로 동작되도록 설정해야 된다.
-->
<!-- Transcation은 advice를 tx:advice 엘리먼트로 등록한다-->
// 트랜잭션 어드바이스(tx:advice)는 AOP를 이용하여 트랜잭션을 적용할 메소드들을 정의합니다.
// tx:attributes 내에서 트랜잭션이 적용될 메소드들을 지정할 수 있습니다.
// get*으로 시작하는 메소드는 읽기 전용(read-only="true")으로 설정하여,
// 트랜잭션이 필요 없음을 명시합니다. 읽기 전용 트랜잭션은 데이터베이스의 변경을 허용하지 않습니다.
// 나머지 모든 메소드(*)는 기본 트랜잭션 동작을 하도록 설정하여,
// 데이터베이스의 변경이 발생할 수 있는 메소드에 트랜잭션을 적용합니다.
<tx:advice id="txAdvice" transaction-manager="txManager">
<!--어떤 이름의 메소드에서 Transaction이 동작할 지 설정-->
<tx:attributes>
<!--get으로 시작하는 메소드에서는 Transaction 동작하지 않음-->
<tx:method name="get*" read-only="true"/>
<!--get으로 시작하는 메소드를 제외한 모든 메소드에서는 Transaction 동작-->
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
4. FreeBoardDao 클래스 수정
// 게시글 등록 쿼리
// ID 추가
private final String POST = "INSERT INTO FREEBOARD(ID, TITLE, CONTENT, WRITER_ID) VALUES(?, ?, ?, ?)";
public void post(BoardDto boardDto) {
System.out.println("FreeBoardDao의 post 메소드 실행");
jdbcTemplate.update(POST, boardDto.getId(), boardDto.getTitle(), boardDto.getContent(), boardDto.getWRITER_ID());
System.out.println("FreeBoardDao의 post 메소드 실행 종료");
}
5. FreeBoardServiceImpl 클래스 수정
// freeBoardDao.post(boardDto); 2번 작성
@Override
public void post(BoardDto boardDto) {
freeBoardDao.post(boardDto);
freeBoardDao.post(boardDto);
}
6. FreeBoardServiceRun 클래스 수정
// primary key 가 중복되도록
// boardDto.setId(50); 추가
public class FreeBoardServiceRun {
public static void main(String[] args) {
AbstractApplicationContext factory =
new GenericXmlApplicationContext("root-context.xml");
BoardService boardService = factory.getBean("freeBoardServiceImpl", BoardService.class);
BoardDto boardDto = new BoardDto();
boardDto.setId(50);
7. 결과
- Duplicate entry(50) 중복된다고 나옴( FreeBoardServiceImpl 클래스에서 freeBoardDao.post(boardDto) 를 2번썼기 때문에..)
- 쿼리를 보면 rollback 되면서 첫 번째 50도 삭제
'백엔드 > Spring Framework' 카테고리의 다른 글
MyBatis (0) | 2024.07.15 |
---|---|
AOP 에서 aspect와 advisor를 사용할 때의 차이점 / Joinpoint와 pointcut의 차이 (2) | 2024.07.14 |
JDBC Template (0) | 2024.07.12 |
AOP(Aspect Oriented Programming) / 관점 지향 프로그래밍 / JoinPoiont 인터페이스 (0) | 2024.07.11 |
AOP(Aspect Oriented Programming) / 관점 지향 프로그래밍 / 동작 시점 (0) | 2024.07.11 |