참고 자료 : 초보 개발자를 위한 스프링5 프로그래밍 입문
<Chapter8. DB 연동>
1. 트랜잭션 처리란?
: 두 개 이상의 쿼리를 한 작업으로 실행해야 할 때
사용하는 것이 바로 트랜잭션이다.
트랜잭션은 여러 쿼리를 논리적으로 하나의 작업으로 묶는 작업이다.
한 트랜잭션으로 묶인 쿼리 중 하나라도 실패할 경우
전체 쿼리를 실패한 것으로 간주하고
DB 상태를 기존 상태로 되돌린다 (롤백)
트랜잭션으로 묶여있는 쿼리가 모두 성공할 경우
commint을 하여 반영한다.
Connection conn=null;
try {
conn= DriverManager.getConnection(jdbcUrl. user, pw);
conn.setAutoCommit(false); // 트랜잭션 범위 시작
--- 쿼리 실행
conn.commit(); // 트랜잭션 범위 종료 : 커밋
} catch(SQLException ex) {
if (conn!=null)
// 트랜잭션 범위 종료 : 롤백
try { conn.rollback();} catch (SQLException e) {}
} finnaly {
if (conn!=null)
try { conn.close();} catch (SQLException e) {}
}
2. @Transactional을 이용한 트랜잭션 처리
: 스프링에서 제공하는 어노테이션을 이용하면
트랜잭션 범위를 매우 쉽게 지정할 수 있다.
트랜잭션 범위에서 실행하고 싶은 메서드에
해당 어노테이션을 붙이면 된다.
@Transactional
public void changePassword(String email, String oldPwd, String newPwd) {
Member member = memberDao.selectByEmail(email);
if (member == null)
throw new MemberNotFoundException();
member.changePassword(oldPwd,newPwd);
memberDao.update(member);
}
selectByEmail과 changePassword 메서드는
동일한 트랜잭션 범위에서 실행한다.
즉, 한 트랜잭션에 묶인다.
@Transactional이 동작하기 위해 스프링 설정에 추가해야한다
1) 플랫폼 트랜잭션 매니저 빈 설정
2) @Transactional 어노테이션 활성화 설정
@Bean
public Platform TransactionManager transactionManager() {
DataSourceTransactionManager tm = new DataSourceTransactionManager();
tm.setDataSource(dataSource());
return tm;
}
PlatformTransactionManger는 스프링에서 제공하는
트랜잭션 매니저 인터페이스이다.
@EnableTransactionManagement 어노테이션은
@Transactional 어노테이션이 붙은 메서드를
트랜잭션 범위에서 실행하는 기능을 활성화한다.
트랜잭션이 시작되고 커밋되는 지 확인하려면
스프링이 출력하는 로그 메세지를 보면 된다.
Logback을 사용하려면
pom.xm 파일이나
build.gradle 파일에 해당 모듈을 추가하자
Logback은 로그 메세지 형식과 기록 위치를
설정 파일에서 읽어온다.
3. @Transactional과 프록시
: 스프링은 해당 어노테이션으로 트랜잭션을 처리하기 위해서
내부적으로 AOP를 사용한다.
AOP는 프록시를 통해 구현이 된다.
따라서 트랜잭션 처리도 프록시를 통해서 이루어진다.
@EnableTransactionManagement 태그를 사용하면
스프링은 @Transactional 어노테이션이 적용된
빈 객체를 찾아서 알맞은 프록시 객체를 생성한다.
스프링은 트랜잭션 기능을 적용하여 프록시 객체를 생성한다.
MainForCPS 클래스에서 getBean 코드를 실행하면
ChangePasswordService 객체 대신에
트랜잭션 처리를 위해 생성한 프록시 객체를 리턴한다
@Transactional 어노테이션이 붙은 메서드를 호출하면
PlatformTransactionManager를 사용해서
트랜잭션을 시작하고
실체 객체의 메서드를 호출한 후
성공적으로 실행되면 트랜잭션을 커밋한다.
4. @Transactional 적용 메서드의 롤백처리 과정
커밋 및 롤백을 처리하는 주체는 프록시 객체이다.
원본 객체의 메서드를 실행하는 과정에서
RuntimeException이 발생하면
트랜잭션을 롤백한다.
별도 설정을 추가하지 않으면
발생한 익셉션이 RuntimeException일 때
트랜잭션을 롤백한다.
SQLException은 RuntimeException을 상속하고 있지 않으므로
SQLException이 발생하면
트랜잭션을 롤백하지 않는다.
만약 해당 익셉션이 발생할 때에도
롤백을 진행하고 싶다면
@Transactional의 rollbackFor 속성을 사용해야함
@Transactional(rollbackFor=SQLException.class)
public void someMethod() {
...
}
4. @Transactional 의 주요 속성
속성 | 타입 | 설명 |
value | String | 트랜잭션을 관리할 때 사용할 PlatformTransactionManagement 빈의 이름을 지정함. 기본값은 " "이다 |
propagation | Propagation | 트랜잭션 전파 타입을 지정함 기본값은 Propagation.REQUIRED > REQUIRED : 메서드 수행시 트랜잭션이 필요하다는 것을 의미함. |
isolation | Isolation | 트랜잭션 격리 레벨을 지정함 기본값은 isolation.DEFAULT |
timeout | int | 트랜잭션 제한 시간을 지정함 기본값은 -1 |
5. @EnableTransactionManagement 어노테이션의 주요 속성
속성 | 설명 |
proxyTargetClass | 클래스를 이용해서 프록시를 생성할지 여부를 지정함. 기본값은 false로서 인터페이스를 이용하여 프록시를 생성함 |
order | AOP 적용 순서를 지정함. 기본값은 가장 낮은 우선순위에 해당하는 int 의 최댓값임 |
6. 트랜잭션 전파
: A 메서드에서 트랜잭션을 시작함
A 메서드에서 B 메서드를 호출하면
이미 A 메서드에 의해 시작된 트랜잭션이 존재하기에
B 메서드 호출시점에 트랜잭션을 새로 생성하지 않고
존재하는 트랜잭션을 그대로 사용한다.
따라서 A메서드와 B메서드를 한 트랜잭션으로
묶어서 실행하게 되는 것을 의미한다.
'여니의 프로그래밍 study > Spring & Spring Boot' 카테고리의 다른 글
[Spring] 스프링 mvc 프레임워크 동작 방식 (Chapter 10) (0) | 2023.11.25 |
---|---|
[Spring] 스프링 mvc 시작하기 (Chapter 9) (0) | 2023.11.23 |
[Spring] DB 연동 - 1(Chapter 8) (1) | 2023.09.16 |
[Spring] AOP 프로그래밍 (Chapter 7) (0) | 2023.09.03 |
[Spring] 컴포넌트 스캔 + 빈 라이브사이클과 범위 (Chapter 5~6) (0) | 2023.08.27 |