2022-03-21(월)
트랜잭션이 필요한 이유
http://localhost:8080/contact/index.html
20자를 넘는 연락처를 등록해보자
1개 밖에 안 들어감
트랜잭션 적용 전
ml_contact (연락처 테이블)
11 홍길동 [email protected]
오류! 전화번호가 20자리를 초과한다!
오류발생 → 메서드 호출 종료 → 요청 처리 중단
그전까지 입력한 값은 그대로 유지
데이터 처리중 오류발생 시 대응 방법
데이터 변경 작업(입력, 변경, 삭제)에 대한 처리 방법
① 데이터 처리 작업 중 일부 작업이 실패하더라도 그전에 수행한 작업은 그대로 승인하는 경우
승인해도 되는 경우
중간에 안내 메시지만 띄워 주면 됨
일부는 규칙을 따르지 않아서 입력 실패입니다
② 데이터 처리 작업 중 일부 작업에 오류 발생시 그전에 수행한 작업을 모두 취소해야 하는 경우
예)
좌석예약 (결제 실패 → 예약 취소)
일부 좌석 예약 실패 → 전체 예약 취소
all or zero
모두 성공하거나 모두 실패해야 됨
주문 (결제실패 → 주문 취소)
모든 데이터 변경 작업이 옳게 수행되거나 모두 취소되어야 하는 상황
→ 트랜잭션 적용 필요
트랜잭션 적용 후
🔹 트랜잭션 : 여러 개의 데이터 조작 작업(입력, 변경, 삭제)을 한 단위로 묶은 것
데이터 조작 (manipulation)
데이터 처리가 단위 별로 수행된다.
단위에 묶인 모든 작업이 성공하면 DB에 적용
① 트랜잭션 적용 전
즉시 적용
② 트랜잭션 적용 후
한 단위로 묶임
임시 DB
commit 전까지 임시 보관
commit 하면 실제 테이블에 적용
만약 오류가 발생하지 않을 경우에만 입력을 완료하고 싶다면
입력 작업들을 한 단위로 묶어라!
트랜잭션을 설정한다
'스프링부트 트랜잭션 설정' 검색
App 클래스 변경
트랜잭션을 활성화시킨다
@EnableTransactionManagement // 애노테이션으로 트랜잭션을 제어할 수 있게 한다.
트랜잭션 관리자 객체 준비
https://spring.io/projects/spring-framework#learn
@Bean
PlatformTransactionManager transactionManager(DataSource ds) {
return new DataSourceTransactionManager(ds);
}
GA : 정식 버전
SNAPSHOT : 개발 버전
PRE : 곧 정식 버전
절대 5.3으로 가면 안 됨
트랜잭션을 적용한다
@RestController
public class ContactController {
@Autowired
ContactDao contactDao;
@Autowired
TransactionTemplate transactionTemplate;
스프링에서 설정하는 방법
Spring에서 트랜잭션 적용하기
35 페이지
1.5.1. Using the TransactionTemplate
TransactionTemplate으로 다루는 방법
https://docs.spring.io/spring-framework/docs/current/javadoc-api/
doInTransaction
<<TransactionCallback>>
doInTransaction() {
트랜잭션으로 묶어서 실행할 작업
}
🔹 TransactionTemplate : 작업 실행 및 트랜잭션 제어
🔹 TransactionManager
• commit()
• rollback()
① excute(↑)
② TransactionTemplate ---call---> ↑
③ TransactionManager
정상 실행 → commit() 호출
예외 발생 → rollback() 호출
객체 지향 : 역할을 쪼개고 각 클래스에게 역할 분담
클래스 관계도를 빨리 파악해야 됨
이 객체가 어떤 일을 하는지 빨리 역할을 파악하기
https://docs.spring.io/spring-framework/docs/current/javadoc-api/
Spring Boot
스프링부트는 패킹한 거
// Spring Boot
• 기본 설정 파일 => *.properties
• 기본 의존 라이브러리 => *.jar
• Web MVC => Spring Framework
• Servlet/JSP => Tomcat Server
스프링부트를 안 쓰고 직접 설정해도 됨
서비스 객체 도입
업무 관련 코드와 트랜잭션 관련 코드를 캡슐화(별도 분리)
① 이전 방식
ContactController ---> ContactDao ---> MyBatis ---> JDBC Driver ---> DBMS
MyBatis는 JDBC Driver 캡슐화 한 거. MyBatis가 내부적으로 호출함.
숨겨져 버림
ContactController
• 요청 파라미터 분석
• 응답 데이터(JSON) 가공
• 업무 로직 + 트랜잭션 제어
ml_contact 테이블, ml_cont_tel 테이블에 insert
=> 분리시키는 게 유지보수에 낫다
② 개선
ContactController
• 요청 파라미터 분석
• 응답 데이터 가공
ContactService
• 업무 로직
• 트랜잭션 제어
ContactController --call--> ContactService
분리 이유
업무 로직을 분리하여 다른 컨트롤러에서 재사용하기 쉽게 한다.
현업에서는 이 방법 사용
'DAO와 테이블 관계' 다시 참고하기
DAO와 테이블 관계 (90-MyList프로젝트2 / 27 페이지)
서비스 객체와 인터페이스
ContactController --call--> ContactService
고객사 A ContactService
A 고객사는 연락처 등록 중 오류가 발생하더라도 그전에 입력한 정보는 승인하기를 원한다
고객사 B ContactService
B 고객사는 연락처 등록 중 오류가 발생하면 그전까지 입력한 정보를 모두 취소하길 원한다.
업무 로직을 별도의 클래스(서비스객체)로 분리하니까
고객사별로 대응하기가 쉬워진다.
개선 사항!
컨트롤러에서 클래스를 바로 사용하게 되면
업무로직 방식이 바뀔 때마다
클래스를 변경해야 한다
=> 유지보수 불편!
요청 파라미터를 가공하는 일은 ContactController가 해야 됨
분리할 때 어떻게 달라지는지..
데이터 처리는 서비스에서 한다
앞으로는 컨트롤러 객체랑 서비스 객체로 분리해야 한다
@Service 붙이기
@Service
public class ContactService {
@Autowired
ContactDao contactDao;
ContactServiceTransaction
@Autowired
TransactionTemplate transactionTemplate;
@Service
public class ContactServiceTransaction {
@Autowired
ContactDao contactDao;
@Autowired
TransactionTemplate transactionTemplate;
functional Interface : 추상메서드가 1개 짜리인 인터페이스
람다 문법을 적용하려면 functional Interface여야 한다.
execute의 리턴 값은 doInTransaction의 리턴 값과 같다
익명 inner class를 파라미터 자리에 둔다
람다 문법까지 적용한 transaction 처리
90-MyList프로젝트2 / 35 페이지 알고 있기
@Service가 안 붙으면 인스턴스를 자동 생성하지 않는다
여기만 바꾸면 됨
ContactServiceTransaction
ContactServiceNonTransaction
개선 사항!
컨트롤러에서 클래스를 바로 사용하게 되면
업무로직 방식이 바뀔 때마다
클래스를 변경해야 한다
=> 유지보수 불편!
해결책
인터페이스 문법
1.5.3. Using the TransactionManager
트랜잭션 실행 정책
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
PROPAGATION_REQUIRED
전파 정책
caller (client)
호출자와 같은 트랜잭션에 묶인다
예외가 발생하면 이전에 수행한 모든 작업들이 취소된다
호출자가 트랜잭션이 없으면
호출자가 트랜잭션에 속해 있지 않으면 새 트랜잭션을 만든 후 실행한다.
PROPAGATION_REQUIRES_NEW
Requires_New
Propagation.SUPPORT
support
Propagation.MANDATORY
Mandatory
Propagation.NOT_SUPPORT
Propagation.NEVER
트랜잭션이 존재하면 에러 뜸
보통은 REQUIRED 사용
DefaultTransactionDefinition 15년 전 기술
2번 방법을 미리 짜놓은 게 TransactionTemplate (1번 방법)
더 쉬운 방법은 @Transactional (3번 방법)
4번째 방법은 AOP
애노테이션조차 붙일 필요 없음
서비스 객체에 인터페이스 적용
특정 클래스에 종속되는 것을 줄일 수 있다
ContactController ---사용---> <<interface>> ContactService
<<interface>> ContactService
을 구현한
ContactServiceNonTransaction
ContactServiceTransaction
ContactServiceTransaction2
ContactServiceTransaction3
중에서 아무거나 꽂으면 된다
직접 클래스를 지정하는 대신에 인터페이스를 지정하면 객체를 교체하기 쉽다
=> 유지보수가 쉽다
html template rendering
javascript template engine
자바스크립트 안에 있는 html 코드를 뜯어낸다
오늘은 13.3 까지...
Author And Source
이 문제에 관하여(2022-03-21(월)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@banana/2022-03-21월저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)