Spring - 10. Transactions

마이바티스 스프링 연동모듈을 사용하는 중요한 이유중 하나는 마이바티스가 스프링 트랜잭션에 자연스럽게 연동될수 있다는 것이다. 마이바티스에 종속되는 새로운 트랜잭션 만드는 것보다 마이바티스 스프링 연동모듈이 스프링과 융합되는 것이좋다.

한마디로 사용자가 그앞의 작업이 안되엇을시 고려를안해도 된다는것이다.

 

어느레스토랑에서 메뉴를 주문하는 실습을 진행할것이다.

 

실습에 진행할 폴더구조입니다.

 

테이블 화면입니다.

TBL_ORDER

 

TBL_ORDER_MENU

 

VO에 관한 파일입니다.

Order.java

package com.memory3.model.vo;

import java.util.List;

public class Order {
	private int code;
	private String date;
	private String time;
	private int orderPrice;
	private List<OrderMenu> menuList;
	
	public Order() { }
	public Order(int code, String date, String time, int orderPrice) {
		super();
		this.code = code;
		this.date = date;
		this.time = time;
		this.orderPrice = orderPrice;
	}
	public int getCode() {
		return code;
	}
	public void setCode(int code) {
		this.code = code;
	}
	public String getDate() {
		return date;
	}
	public void setDate(String date) {
		this.date = date;
	}
	public String getTime() {
		return time;
	}
	public void setTime(String time) {
		this.time = time;
	}
	public int getOrderPrice() {
		return orderPrice;
	}
	public void setOrderPrice(int orderPrice) {
		this.orderPrice = orderPrice;
	}
	
	public List<OrderMenu> getMenuList() {
		return menuList;
	}
	public void setMenuList(List<OrderMenu> menuList) {
		this.menuList = menuList;
	}
	@Override
	public String toString() {
		return "Order [code=" + code + ", date=" + date + ", time=" + time + ", orderPrice=" + orderPrice
				+ ", menuList=" + menuList + "]";
	}
	
}

 

OrderMenu.java

package com.memory3.model.vo;

public class OrderMenu {
	private int orderCode;
	private int menuCode;
	private int amount;
	
	public OrderMenu() { 	}

	public OrderMenu(int orderCode, int menuCode, int amount) {
		super();
		this.orderCode = orderCode;
		this.menuCode = menuCode;
		this.amount = amount;
	}

	public int getOrderCode() {
		return orderCode;
	}

	public void setOrderCode(int orderCode) {
		this.orderCode = orderCode;
	}

	public int getMenuCode() {
		return menuCode;
	}

	public void setMenuCode(int menuCode) {
		this.menuCode = menuCode;
	}

	public int getAmount() {
		return amount;
	}

	public void setAmount(int amount) {
		this.amount = amount;
	}

	@Override
	public String toString() {
		return "OrderMenu [orderCode=" + orderCode + ", menuCode=" + menuCode + ", amount=" + amount + "]";
	}
	
}

 

마이바티스 설정 xml파일입니다.

mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
	
	<mappers>
		<mapper resource="com/memory3/model/dao/OrderMapper.xml"/>
	</mappers>
</configuration>

 

스프링 기본설정 xml파일입니다.

spring-context.xml

dataSource, sessionFactoryBean, sqlSessionTemplate 빈은 기초연결에 설정되는부분이고

component-scan 은 현재 xml기준 폴더로 빈을 스캔하는데 구조가 다른폴더로 되어있어 직접 스캔위치를 지정해주는 기능이다.

mybatis-spring 기능은 마이바티스에서 제공하는 자동으로 dao를 매칭시켜주는역할이고,

transactionManager 부분이 이번에 실습에필요한 빈이다 자동주입을위해 등록해두었다.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mybatis-spring="http://mybatis.org/schema/mybatis-spring"
	xsi:schemaLocation="http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring-1.2.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-4.3.xsd">
	<context:property-placeholder location="connection-info.properties"/>
	
	<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
		<property name="driverClassName" value="${oracle.dev.driver}"/>
		<property name="url" value="${oracle.dev.url}"/>
		<property name="username" value="${oracle.dev.username}"/>
		<property name="password" value="${oracle.dev.password}"/>
		<property name="defaultAutoCommit" value="false"/>
	</bean>
	
	<bean id="sessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="dataSource" ref="dataSource"/>
		<property name="configLocation" value="com/memory3/config/mybatis-config.xml"/>
	</bean>
	
	<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
		<constructor-arg name="sqlSessionFactory" ref="sessionFactoryBean"/>
	</bean>
	
	<context:component-scan base-package="com.memory3"/>
	
	<mybatis-spring:scan base-package="com.memory3.model.dao"/>
	
	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"/>
	</bean>
	
</beans>

 

Main 실행에 위한 class파일입니다.

Application.java

package com.memory3.run;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Scanner;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;

import com.memory3.model.service.OrderService;
import com.memory3.model.vo.Order;
import com.memory3.model.vo.OrderMenu;

public class Application {

	public static void main(String[] args) {
		
		ApplicationContext context = new GenericXmlApplicationContext("com/memory3/config/spring-context.xml");
		
		Order order = new Order();
		OrderMenu orderMenu;
		List<OrderMenu> orderMenuList = new ArrayList<>();
		
		Scanner sc = new Scanner(System.in);
		do {
			System.out.println("========== 레스토랑 음식 주문 서비스 ==========");
			System.out.print("어떤 메뉴를 주문하시겠습니까?(코드입력) : ");
			int menuCode = sc.nextInt();
			System.out.print("주문 수량을 입력해주세요 : ");
			int amount = sc.nextInt();
			sc.nextLine();
			System.out.print("다른 메뉴를 추가로 주문하시겠습니까?(Y/N) : ");
			char addMenuYN = sc.nextLine().toUpperCase().charAt(0);
			
			orderMenu = new OrderMenu();
			orderMenu.setMenuCode(menuCode);
			orderMenu.setAmount(amount);
			
			orderMenuList.add(orderMenu);
			
			if(addMenuYN != 'Y') {
				break;
			}
			
		}while(true);
		
		SimpleDateFormat date = new SimpleDateFormat("yyyyMMdd");
		SimpleDateFormat time = new SimpleDateFormat("HH:mm:ss");
		
		order.setDate(date.format(new Date()));
		order.setTime(time.format(new Date()));
		order.setMenuList(orderMenuList);
		
		// System.out.println(order);
		
		OrderService orderService = context.getBean("orderService", OrderService.class);
		
		int result1 = orderService.insertMenu(order);
		
		if(result1 > 0) {
			System.out.println("메뉴 주문에 성공하였습니다.");
		}else {
			System.out.println("메뉴 주문에 실패하였습니다.");
		}
	}

}

 

OrderService.interface

package com.memory3.model.service;

import com.memory3.model.vo.Order;

public interface OrderService {
	int insertMenu(Order order);
}

 

OrderServiceImpl.java

package com.memory3.model.service;

import java.sql.SQLException;

import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import com.memory3.model.dao.OrderMapper;
import com.memory3.model.vo.Order;
import com.memory3.model.vo.OrderMenu;

@Service("orderService")
public class OrderServiceImpl implements OrderService{
	private SqlSessionTemplate sqlSessionTemplate;
	private DataSourceTransactionManager transactionManager;

	@Autowired
	public OrderServiceImpl(SqlSessionTemplate sqlSessionTemplate, DataSourceTransactionManager transactionManager) {
		this.sqlSessionTemplate = sqlSessionTemplate;
		this.transactionManager = transactionManager;
	}

	@Override
	public int insertMenu(Order order) {
		DefaultTransactionDefinition def = new DefaultTransactionDefinition();
		def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
		def.setIsolationLevel(DefaultTransactionDefinition.ISOLATION_SERIALIZABLE);
		
		TransactionStatus status = transactionManager.getTransaction(def);
		
		try {
			sqlSessionTemplate.getConnection().setAutoCommit(false);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		
		
		OrderMapper orderMapper = sqlSessionTemplate.getMapper(OrderMapper.class);
		
		int result = 0;
		
		int result1 = orderMapper.insertMenu(order);
		
		if(result1 > 0) {
			int result2 = 0;
			for(OrderMenu orderMenu : order.getMenuList()) {
				result2 += orderMapper.insertMenuOrder(orderMenu);
			}
			
			if(result2 > 0) {
				result = 1;
				transactionManager.commit(status);
			}else {
				transactionManager.rollback(status);
			}
		}
		return result;
	}
	
	
}

 

OrderMapper.interface

package com.memory3.model.dao;

import com.memory3.model.vo.Order;
import com.memory3.model.vo.OrderMenu;

public interface OrderMapper {
	int insertMenu(Order order);
	
	int insertMenuOrder(OrderMenu orderMenu);
}

OrderMapper.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.memory3.model.dao.OrderMapper">
	<insert id="insertMenu" parameterType="com.memory3.model.vo.Order">
		INSERT
		  INTO TBL_ORDER
		  	   (
		  	   		ORDER_CODE
		  	   	  , ORDER_DATE
		  	   	  , ORDER_TIME
		  	   	  , TOTAL_ORDER_PRICE
		  	   )
		VALUES 
			   (
			   		SEQ_ORDER_CODE.NEXTVAL
			   	  , #{date}
			   	  , #{time}
			   	  , #{orderPrice}
			   )
	</insert>
	
	<insert id="insertMenuOrder" parameterType="com.memory3.model.vo.OrderMenu">
		<selectKey resultType="_int" keyProperty="orderCode" order="BEFORE">
			SELECT
				   SEQ_ORDER_CODE.CURRVAL
			  FROM DUAL
		</selectKey>
		INSERT
		  INTO TBL_ORDER_MENU
		       (
		       		ORDER_CODE
		       	  , MENU_CODE
		       	  , ORDER_AMOUNT
		       )
	    VALUES 
	    	   (
	    	   		#{orderCode}
	    	   	  , #{menuCode}
	    	   	  , #{amount}
	    	   )
	</insert>
</mapper>

 

실행화면

 

 

'프로그래밍 > Spring' 카테고리의 다른 글

Spring - 12. MAVEN  (0) 2021.10.26
Spring - 11. Transactions AOP  (0) 2021.10.26
Spring - 9. mapperscan  (0) 2021.10.25
Spring - 6_2. Spring JDBC (XML)  (0) 2021.10.25
Spring - 8. 다국어 메세지  (0) 2021.10.22
  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유