SPRING - 스프링 트랜잭션(1)

이번엔 트랜잭션에 대해 알아보겠습니다

트랜잭션은 논리적 단위로 어떤 한 부분의 작업이

완료되었다 하더라도 다른 부분의 작업이 완료되지

않을 경우 전체작업이 취소가되는 것입니다.

이때 작업이 완료되는 것을 커밋이라고 하고

작업이 취소되는 것을 롤백 이라고 합니다


우리들은 일상생활에서 트랜잭션의 예를 많이

볼 수 있습니다. 우리는 영화 예매를 할 경우

카드 결제 작업과 마일리지 적립 작업을 볼수있습니다

이때의 작업들은 트랜잭션으로 작동해야 합니다

또한 은행 ATM기기와 쇼핑몰에서도 마찬가지 입니다.


먼저 테스트를 해보겠습니다.

이번 테스트를 하기 위해서는 이전 포스팅을

먼저 보셔야 합니다.


먼저 티켓 구매를 위한 간단한 jsp화면을 만들어줍니다

buy_ticket.jsp


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
 
<p>카드 결제</p>
 
<form action="buy_ticket_card">
    고객 아이디 : <input type="text" name="consumerId" > <br />
    티켓 구매수 : <input type="text" name="amount" > <br />
    <input type="submit" value="구매" > <br />
</form>
 
</body>
</html>
cs


다음 컨트롤러 보겠습니다


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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
package com.spring.ex;
 
import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;
 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
 
import com.spring.ex.dao.TicketDao;
import com.spring.ex.dto.TicketDto;
 
@Controller
public class HomeController {
    
    private TicketDao dao;
    
    @Autowired
    public void setDao(TicketDao dao) {
        this.dao = dao;
    }
    
    private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
    
    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String home(Locale locale, Model model) {
        logger.info("Welcome home! The client locale is {}.", locale);
        
        Date date = new Date();
        DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);
        
        String formattedDate = dateFormat.format(date);
        
        model.addAttribute("serverTime", formattedDate );
        
        return "home";
    }
    
    @RequestMapping("/buy_ticket")
    public String buy_ticket() {
        return "buy_ticket";
        
    }
    
    @RequestMapping("/buy_ticket_card")
    public String buy_ticket_card(TicketDto ticketDto, Model model) {
        System.out.println"buy_ticket_card" );
        System.out.println"ticketDto : " + ticketDto.getConsumerId() );
        System.out.println"ticketDto : " + ticketDto.getAmount() );
        
        dao.buyTicket(ticketDto);
        
        model.addAttribute("ticketInfo", ticketDto);
        
        return "buy_ticket_end";
    }
    
}
 
cs


buy_ticket.jsp 에서 구매자 아이디와

구매하려는 티켓 갯수를 입력하면 

buy_ticket_card로 action되서 컨트롤러로 오게됩니다

다음 sysout으로 값들을 출력하고

56line에서 dao를 이용해 db에 접근해 값들을

insert 해줍니다.


다음 TicketDao 보겠습니다.


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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
package com.spring.ex.dao;
 
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementCreator;
 
import com.spring.ex.dto.TicketDto;
 
public class TicketDao {
 
    JdbcTemplate template;
    
    @Autowired
    public void setTemplate(JdbcTemplate template) {
        this.template = template;
    }
    
    public TicketDao() {
        System.out.println(template);
    }
    
    public void buyTicket(final TicketDto dto) {
        System.out.println("buyTicket()");
        System.out.println("dto.getConsumerId() : " + dto.getConsumerId());
        System.out.println("dto.getAmount() : " + dto.getAmount());
        
        template.update(new PreparedStatementCreator() {
            
            @Override
            public PreparedStatement createPreparedStatement(Connection con)
                    throws SQLException {
                String query = "insert into card (consumerId, amount) values (?, ?)";
                PreparedStatement pstmt = con.prepareStatement(query);
                pstmt.setString(1, dto.getConsumerId());
                pstmt.setString(2, dto.getAmount());
                
                return pstmt;
            }
        });
        
        template.update(new PreparedStatementCreator() {
            
            @Override
            public PreparedStatement createPreparedStatement(Connection con)
                    throws SQLException {
                String query = "insert into ticket (consumerId, countnum) values (?, ?)";
                PreparedStatement pstmt = con.prepareStatement(query);
                pstmt.setString(1, dto.getConsumerId());
                pstmt.setString(2, dto.getAmount());
                
                return pstmt;
            }
        });
    }
 
    
}
 
cs


DAO에서는 구매자 아이디와 구매하려는

티켓수 등을 insert 해줍니다


다음 서블릿 컨텍스트입니다


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
31
32
33
34
35
36
37
38
39
40
41
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
 
    <!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
    
    <!-- Enables the Spring MVC @Controller programming model -->
    <annotation-driven />
 
    <!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
    <resources mapping="/resources/**" location="/resources/" />
 
    <!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
    <beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <beans:property name="prefix" value="/WEB-INF/views/" />
        <beans:property name="suffix" value=".jsp" />
    </beans:bean>
    
    <context:component-scan base-package="com.spring.ex" />
    <beans:bean name="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <beans:property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
        <beans:property name="url" value="jdbc:oracle:thin:@localhost:1521:xe" />
        <beans:property name="username" value="scott" />
        <beans:property name="password" value="tiger" />
    </beans:bean>
    
    <beans:bean name="template" class="org.springframework.jdbc.core.JdbcTemplate">
        <beans:property name="dataSource" ref="dataSource" />
    </beans:bean>
    
    <beans:bean name="dao" class="com.spring.ex.dao.TicketDao" >
        <beans:property name="template" ref="template" />
    </beans:bean>
    
</beans:beans>
 
cs


TicketDto.java 입니다


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.spring.ex.dto;
 
public class TicketDto {
 
    private String consumerId;
    private String amount;
    
    public String getConsumerId() {
        return consumerId;
    }
    public void setConsumerId(String consumerId) {
        this.consumerId = consumerId;
    }
    public String getAmount() {
        return amount;
    }
    public void setAmount(String amount) {
        this.amount = amount;
    }
    
}
cs


마지막으로 buy_ticket_end 입니다


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
 
buy_ticket_end.jsp 입니다. <br />
 
${ticketInfo.consumerId } <br />
${ticketInfo.amount } <br />
 
 
</body>
</html>
cs


이제 DB에 card, ticket 테이블을 만든후

테스트를 해봅니다 ticket 테이블에서

5장이상 구매할수 없도록 제약조건을 달아줍니다

테이블 생성방법은 생략합니다




제약조건은 위 이미지처럼 달수 있습니다.

 

 이제 프로그램을 실행시켜서 테스트해봅니다

이 소스들에는 롤백 기능이 들어있지 않습니다.



--



--



먼저 카드 결제 란에

aaa아이디로 3개의 티켓 결제가

정상적으로 됬습니다.



다음 티켓 테이블에도 3개의

티켓이 발권된것을 확인할수 있습니다.


이제 5장이상의 티켓을 구매해 보겠습니다




5장 이상 티켓을 구매하면 위처럼 에러가 발생합니다.



6장의 티겟이 카드로 결제가 되었지만


위 이미지를 보시면 결제된 티켓이

발권이 되지 않았습니다.


다음 포스팅에서 롤백 추가하겠습니다.



'SPRING' 카테고리의 다른 글

SPRING - 스프링 트랜잭션(3)  (0) 2018.02.08
SPRING - 스프링 트랜잭션(2)  (0) 2018.02.08
SPRING - 스프링JDBC, @Autowired  (0) 2018.02.08
SPRING - @Valid 와 @InitBinder  (0) 2018.02.07
SPRING - ValidationUtils 클래스  (0) 2018.02.07

댓글

Designed by JB FACTORY