-
[Boot] TransactionSpring/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