티스토리 뷰
초보 웹 개발자를 위한 스프링 5 프로그램 입문을 보고 복습 겸 개인 학습 정리입니다. (windows 기준)
트랜잭션 (Transaction)
두 개 이상의 쿼리를 한 작업으로 실행해야 할 때 사용하는 것
여러 쿼리를 논리적으로 하나의 작업으로 묶어준다.
한 트랜잭션으로 묶인 쿼리 중 하나라도 실패하면 전체 쿼리를 실패로 간주하고 실패 이전에 실행된 쿼리를 취소한다.
트랜잭션도 공통 기능 중 하나로 프록시를 통해 이루어진다.
※ 프록시 : 핵심 기능의 실행은 다른 객체에 위임하고 부가적인 기능을 제공하는 객체
트렌잭션으로 묶인 모든 쿼리가 성공해서 쿼리 결과를 DB에 실제 반영하는 것을 커밋(commit)이라고 한다.
쿼리 실행 결과를 취소하고 DB를 기존 상태로 되돌리는 것을 롤백(roll back)이라고 부른다.
@Transactional을 이용한 트랜잭션 처리
스프링이 제공하는 @Transactional 애노테이션을 사용하면 쉽게 트랜잭션 범위를 지정할 수 있다.
트랜잭션 범위에 실행하고 싶은 메서드에 @Transactional 애노테이션을 붙이면 된다.
@Transactional 애노테이션이 제대로 동작하려면 다음 두 설정을 스프링 설정에 추가해야 한다.
- 플랫폼 트랜잭션 매니저 빈 설정 (Platform Transaction Manager)
- @Transactional 애노테이션 활성화 설정
예제 AppCtx 설정 클래스에 트랜젝션 관련 설정을 추가하자.
@EnableTransactionManagement 추가와 PlatformTransactionManager 빈을 추가
@EnableTransactionManagement 애노테이션은 @Transactional 애노테이션이 붙은 메서드를 트랜잭션 범위에서 실행하는 기능을 활성화한다. 등록된 PlatformTransactionManager 빈을 사용해서 트랜젝션을 적용한다.
설정 클래스(AppCtx.java)에 @EnableTransactionManagement을 추가하고 플랫폼 트랜잭션 매니저 빈 설정과 비밀번호 변경 서비스 클래스 빈을 추가한다.
→sp5-chap08/src/main/java/config/AppCtx.java
package config;
// ... import 생략...
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
@EnableTransactionManagement
// @Transection 애노테이션이 붙은 메서드를 트랜잭션 범위에서 실행하는 기능을 활성화
public class AppCtx {
@Bean(destroyMethod = "close")
public DataSource dataSource() {
DataSource ds = new DataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost/spring5fs?characterEncoding=utf8&useSSL=false");
ds.setUsername("spring5");
ds.setPassword("0000");
ds.setInitialSize(2);
ds.setMaxActive(10);
ds.setTestWhileIdle(true);
ds.setMinEvictableIdleTimeMillis(60000 * 3);
ds.setTimeBetweenEvictionRunsMillis(10 * 1000);
return ds;
}
// 플랫폼트랜잭션 매니저 스프링 빈 생성
@Bean
public PlatformTransactionManager transactionManager() {
DataSourceTransactionManager tm = new DataSourceTransactionManager(null);
tm.setDataSource(dataSource());
return tm;
}
// 비밀번호 변경 서비스 클래스 빈 추가
@Bean
public ChangePasswordService changePwdSvc() {
ChangePasswordService pwdSvc = new ChangePasswordService();
pwdSvc.setMemberDao(memberDao());
return pwdSvc;
}
@Bean
public MemberDao memberDao() {
return new MemberDao(dataSource());
}
}
다음으로 트랜잭션 범위에 실행하고 싶은 스프링 빈객체의 메서드에 @Transactional 애노테이션을 붙이자.
→sp5-chap08/src/main/java/spring/ChangePasswordService.java
package spring;
import org.springframework.transaction.annotation.Transactional;
public class ChangePasswordService {
private MemberDao memberDao;
@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);
}
public void setMemberDao(MemberDao memberDao) {
this.memberDao = memberDao;
}
}
트랜잭션 설정을 실행하는 메인 클래스를 작성한다.
→sp5-chap08/src/main/java/main/MainForCPS.java
package main;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import config.AppCtx;
import spring.ChangePasswordService;
import spring.MemberNotFoundException;
import spring.WrongIdPasswordException;
public class MainForCPS {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppCtx.class);
ChangePasswordService cps = ctx.getBean("changePwdSvc", ChangePasswordService.class);
try {
cps.changePassword("a@a.com","1234", "0000");
System.out.println("암호를 변경했습니다.");
}catch (MemberNotFoundException e) {
System.out.println("회원 데이터가 존재하지 않습니다.");
}catch (WrongIdPasswordException e) {
System.out.println("암호가 올바르지 않습니다.");
}
ctx.close();
}
}
트랜잭션이 시작되고 커밋되는지 확인하기 위해 pom 파일에 Logback모듈을 추가하고, Logback 설정 파일을 만들고 추가한다. 내용이 길어 접은 글로 대체
→sp5-chap08/pom.xml
<dependency>
<groupId> mysql </groupId>
<artifactId> mysql-connector-java </artifactId>
<version>5.1.45 </version>
</dependency>
<dependency>
<groupId> org.slf4j </groupId>
<artifactId> slf4 j-api </artifactId>
<version>1.7.24 </version>
</dependency>
<dependency>
<groupId> ch.qos.logback </groupId>
<artifactId> logback-classic </artifactId>
<version>1.2.3 </version>
</dependency>
스프링의 JDBC 관련 모듈에서 출력하는 로그 메시지를 상세하게("DEBUG" 레벨) 보기 위한 설정
→sp5-chap08/src/main/resources/logback.xml
<? xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>% d %5p % c {2} - % m% n </pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="stdout" />
</root>
<logger name="org.springframework.jdbc" level="DEBUG" />
</configuration>
롤백 확인을 위한 파일 설정들을 마치고 MainForCPS 클래스를 실행
※ MainForCPS클래스의 try 구문의 cps.changePassword("a@a.com", "1234", "0000"); 괄호 안에 패스워드를 직접 입력해야 한다.
암호 변경이 이뤄졌을 때
→ 정상적으로 트랜잭션을 커밋한다는 로그를 확인할 수 있다.
암호 인증에 실패했을 때
→ 트랜잭션이 롤백되는 로그를 확인할 수 있다.
@Transactional 주요 속성 (책 p.223 참고하기)
속성 | 타입 | 설명 |
value | String | 트랜잭션을 관리할 때 사용할 PlatformTransactionManager의 빈의 값을 지정 기본값 " "이다. |
propagation | Propagation | 트랜잭션 전파 타입을 지정한다. 기본값 Propagation.REQUIRED |
isolation | isolation | 트랜잭션 격리 레벨을 지정한다. 기본값 lsolation.DEFAULT |
timeout | int | 트랜잭션 제한 시간을 지정한다. 기본값 -1로 이경우 db의 타임아웃 시간을 사용. 초 단위로 지정 |
value 속성값이 없으면 타입이 PlatformTransactionManager인 빈을 사용
AppCtx 클래스에 PlatformTransactionManager를 트랜잭션 관리자로 사용했었다.
'study > Spring' 카테고리의 다른 글
chap 09 - 스프링 MVC 설정 (0) | 2023.01.30 |
---|---|
Tomcat 설치 (0) | 2023.01.25 |
chap 08 - DB 연동 jdbcTemplate 쿼리 실행 (0) | 2023.01.18 |
chap 08 - DB 연동 DataSource 설정 (1) | 2023.01.13 |
chap 07 - AOP 프로그래밍 (0) | 2023.01.10 |
- Total
- Today
- Yesterday
- 암호화
- Java
- django.contrib.auth
- python3
- 혼자 공부하는 파이썬
- authenticate()
- 웹페이지
- Django tutorial
- git공부
- 회원 로그인
- git 공부
- API
- Python
- 검색 결과 내 페이지네이션
- 환경 변수 설정
- musma
- error: failed to push some refs to 'https://github.com/
- Magazine K
- 면접을 위한 CS 전공 지식 노트
- Spring
- 배열
- django-environ
- git
- 디자인 패턴
- 커맨드 객체
- path variable
- 톰캣
- 회원가입
- django
- 한글 형태소 분석기
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |