ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Boot] Transaction
    Spring/Boot 2022. 9. 10. 21:08

    동작에 오류가 발생하면 처음 상태로 되돌림

    sql.sql

    drop table transaction1;
    drop table transaction2;
    drop table transaction3;
    
    create table transaction1(
    id varchar2(20),
    amount number(10)
    );
    create table transaction2(
    id varchar2(20),
    amount number(10)
    );
    create table transaction3(
    id varchar2(20),
    amount number(10)
    );
     
     

     

    Controller

    package com.ecl.g13.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    @Controller
    public class MyController {
    
    	@RequestMapping("/")
    	public String root() {
    		return "buy_ticket";
    	}
    이 안에 추가될 코드 배경 - 줄무늬
    }

    buy_ticket.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>buy_ticket</title>
    </head>
    <body>
    
    <p>카드 결제</p>
    <form action="butTicketCard">
    	고객 아이디: <input type="text" name="id"><br/>
    	티켓 구매수: <input type="text" name="amount"><br/>
    	에러 발생 여부: <input type="text" name="error" value="0"><br/>
    	<input type="submit" value="구매"><br/>
    </form>
    <hr>
    에러 발생 여부에 1을 입력하면 에러가 발생함
    
    </body>
    </html>

     

    Controller

    	@Autowired
    	MyService ms;
    
    	@RequestMapping("/buyTicketCard")
    	public String buy_ticket_card(
    		@RequestParam("id") String id,
    		@RequestParam("amount") int amount,
    		@RequestParam("error") int error, Model model) {
    		// 현재 해야할 일은 전달된 아이디가 티켓을 전달된 구매갯수만큼 
    		// 구매한 걸로 데이터베이스 테이블에 insert 하는 것
    		int result = ms.buy(id, amount, error);
    		// 전달된 아이디, 구매갯수, 에러여부를 서비스단에 전달하여 구매작업을 계속진행
    		// 구매작업 성공여부를 리턴받아서 성공이면 buy_ticket_end.jsp로
    		// 실패하면 buy_ticket_error.jsp로 이동
    		
    		model.addAttribute("id",id);
    		model.addAttribute("amount",amount);
    		model.addAttribute("error",error);
    		
    		if(result == 1) return "buy_ticket_end";
    		else return "buy_ticket_error";
    	}

    Service

    package com.ecl.g13.service;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import com.ecl.g13.dao.ITransactionDao1;
    import com.ecl.g13.dao.ITransactionDao2;
    
    @Service
    public class MyService {
    
    	@Autowired
    	ITransactionDao1 td1;
    	
    	@Autowired
    	ITransactionDao2 td2;
    	
    	public int buy(String id, int amount, int error) {
    		int result = 0;
    
    		td1.buy(id, amount);
    		if(error == 1) {
    			int n = 10 / 0; // 전달된 error 값이 1이라면 강제 에러 발생
    		}
    		
    		td2.buy(id, amount);
    
    		if(error == 1) result = 0;
    		else result = 1;
    
    		return result;
    	}
    }

    interface Dao

    package com.ecl.g13.dao;
    
    import org.apache.ibatis.annotations.Mapper;
    
    @Mapper
    public interface ITransactionDao1 {
    	public void buy(String id, int amount);
    }
    package com.ecl.g13.dao;
    
    import org.apache.ibatis.annotations.Mapper;
    
    @Mapper
    public interface ITransactionDao2 {
    	public void buy(String id, int amount);
    }

    src\main\resources\mybatis\mapper\TransactionDao1.xml

    <?xml version="1.0" encoding="UTF-8"?>
    
    <!DOCTYPE mapper  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
        
    <mapper namespace = "com.ecl.g13.dao.ITransactionDao1" >
    	<insert id="buy">
    		insert into transcation1(id, amount) values(#{param1}, #{param2})
    	</insert>
    </mapper>

    src\main\resources\mybatis\mapper\TransactionDao2.xml

    <?xml version="1.0" encoding="UTF-8"?>
    
    <!DOCTYPE mapper  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
        
    <mapper namespace = "com.ecl.g13.dao.ITransactionDao2" >
    	<insert id="buy">
    		insert into transcation2(id, amount) values(#{param1}, #{param2})
    	</insert>
    </mapper>

    buy_ticket_end.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>buy_ticket_end.jsp</title>
    </head>
    <body>
    
    <h1>buy_ticket_end</h1>
    <h1>티켓의 아래의 정보로 정상 구매 되었습니다.</h1>
    <h2>아이디: ${id }</h2>
    <h2>수량: ${amount }</h2>
    <h2>에러: ${error }</h2>
    
    </body>
    </html>

    buy_ticket_error.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>buy_ticket_error.jsp</title>
    </head>
    <body>
    
    <h1>buy_ticket_error</h1>
    <h1>에러 발생</h1>
    <h2>아이디: ${id }</h2>
    <h2>수량: ${amount }</h2>
    <h2>에러: ${error }</h2>
    
    </body>
    </html>

    Service

    	@Autowired
    	PlatformTransactionManager ptm;
    	
    	@Autowired
    	TransactionDefinition td;
    
    	public int buy(String id, int amount, int error) {
    		int result = 0;
    		// 전달된 아이디와 구매갯수를 transaction1,transaction2 
    		// 두 개의 테이블에 insert함
    		// 하나 이상의 데이터베이스 작업을 묶어서
    		// 하나의 실행단위로 정의된 것을 트랙잭션이라고 함
    		// 트랙잭션 하나가 모두 다 실행이 되어 완료되면
    		// commit이라는 명령으로 작업을 완료하고
    		// 중간에 에러가 발생하면 트랙잭션을 취소하고자 한다면
    		// rollback이라는 명령을 취소함
    		
    		// 트랙잭션의 시작
    		TransactionStatus status = ptm.getTransaction(td);
    		// 끝은 commit 또는 rollback
    		
    		try {
    			td1.buy(id, amount);
    			if(error == 1) {
    				int n = 10 / 0;
    			}
    			td2.buy(id, amount);
    			System.out.println("error없이 둘 다 실행됨");
    			ptm.commit(status); 
    			// 영역 안의 모든 데이터베이스 작업의 실행적용 - 트랙잭션 끝
    			result = 1;
    		} catch(Exception e) {
    			System.out.println("error나서 실행 안됨");
    			ptm.rollback(status);
    			// 영역 안의 모든 데이터베이스 작업의 취소
    			result = 0;
    		}
    		return result;
    	}
     

    방법 2

    Service

    	@Autowired
    	TransactionTemplate tt;
    
    	public int buy(String id, int amount, int error) {
    		try {
    			tt.execute(new TransactionCallbackWithoutResult() {
    
    				@Override
    				protected void doInTransactionWithoutResult(TransactionStatus status){
    					// 현재 트랙잭션에 포함될 명령들을 이 위치에 기술함
    					td1.buy(id, amount);
    					if(error == 1) {
    						int n = 10 / 0;
    					}
    					td2.buy(id, amount);
    				}
    			});
    			return 1;
    		} catch(Exception e){
    			return 2;
    		}
    	}

    'Spring > Boot' 카테고리의 다른 글

    [Boot] Use procedure  (0) 2022.09.10
    [Boot] MyBatis  (0) 2022.09.10
    [Boot] JDBC  (0) 2022.09.10
    [Boot] Validation  (0) 2022.09.10
    [Boot] Lombok  (0) 2022.09.10

    댓글

Designed by Tistory.