myBatis - 6. 구문 빌더(SelectBuilder, SqlBuilder)

자바 개발자에게 가장 끔직한 일중 하나는 자바 코드에서 내장 SQL 을 처리하는 것이다. SQL은 항상 동적으로 생성되기 때문에, 파일이나 저장 프로시저를 외부에 둘수도 있다. Mybatis는 XML 매핑에서 동적으로 SQL을 생성하기 위한 강력한 대답이 될것이다. 자바코드에서 SQL 구문을 문자열로 만들어야 할 필요가 종종 있다. 이경우 MyBatis를 좀더 쉽게 만들도록 해준다. 이기능은 +, 따옴표, 개행문자 그리고 콤마와 AND 등의 포맷팅에 관련된 작업을 줄여준다.

 

한마디로 쿼리문을 XML이아닌데 class파일에서 SQL클래스의 메소드이용해 작업해주는다는것이다.

하다보면 편리하고 쉽다.

 

SelectBuilder : 조회할떄 사용하고

SqlBuilder : insert, delete, update 시 사용된다고 생각하면 편합니다.

 

SelectBuilder와 SqlBuilder 이용하여 실습진행할려고합니다.

목차는 아래와 같습니다.

 

1. SelectBuilder 테스트하기

  (1). SelectBuilder 기본 구문 사용하기

  (2). SelectBuilder를 이용한 동적 SQL 사용하기

2. SqlBuilder 테스트하기

  (1). 새로운 메뉴 추가하기

  (2). 기존 메뉴 수정하기

  (3). 마음에 들지 않는 메뉴 삭제하기

 

순으로 진행할려고합니다.

위의코드는 학원에서 배운내용을 복습개념으로 한번더 혼자 작업해보기위해 만든코드입니다.

 

공통

config.xml

마이바티스 커넥션 정보를 공통으로 관리하기위한 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>

  <properties resource="driver.properties"/>
  
  <!-- 별칭 -->
  <typeAliases>
  	<typeAlias type="com.memory.model.vo.Search" alias="search"/>
  </typeAliases>
  
  <environments default="dev">
    <environment id="dev">
      <transactionManager type="JDBC"/>
      <dataSource type="POOLED">
        <property name="driver" value="${driver}"/>
        <property name="url" value="${url}"/>
        <property name="username" value="${username}"/>
        <property name="password" value="${password}"/>
      </dataSource>
    </environment>
  </environments>
  
  <mappers>
  	<package name="com.memory.model.dao"/>
  	<package name="com.memory2.model.dao"/>
  </mappers>
  
</configuration>

driver.properties

JDBC 접속정보를 저장하기위한 프로퍼티 파일

driver=oracle.jdbc.driver.OracleDriver
url=jdbc:oracle:thin:@localhost:1521:xe
username=mybatis
password=mybatis

 

Menu.java

메뉴의 정보를 담기위한 파일

package com.memory2.model.vo;

public class Menu {
	private int code;
	private String name;
	private int price;
	private int categoryCode;
	private String orderableStatus;
	
	public Menu() {
		super();
	}
	
	public Menu(String name, int price, int categoryCode) {
		super();
		this.name = name;
		this.price = price;
		this.categoryCode = categoryCode;
	}

	public Menu(int code, String name, int price, int categoryCode, String orderableStatus) {
		super();
		this.code = code;
		this.name = name;
		this.price = price;
		this.categoryCode = categoryCode;
		this.orderableStatus = orderableStatus;
	}

	public int getCode() {
		return code;
	}

	public void setCode(int code) {
		this.code = code;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getPrice() {
		return price;
	}

	public void setPrice(int price) {
		this.price = price;
	}

	public int getCategoryCode() {
		return categoryCode;
	}

	public void setCategoryCode(int categoryCode) {
		this.categoryCode = categoryCode;
	}

	public String getOrderableStatus() {
		return orderableStatus;
	}

	public void setOrderableStatus(String orderableStatus) {
		this.orderableStatus = orderableStatus;
	}

	@Override
	public String toString() {
		return "Menu [code=" + code + ", name=" + name + ", price=" + price + ", categoryCode=" + categoryCode
				+ ", orderableStatus=" + orderableStatus + "]";
	}
	
	
	
	
}

 

 

Search.java

검색 조건,값을 저장하기위한 파일

package com.memory2.model.vo;

public class Search {
	private String condition;
	private String value;
	
	public Search() {
		super();
	}

	public Search(String condition, String value) {
		super();
		this.condition = condition;
		this.value = value;
	}

	public String getCondition() {
		return condition;
	}

	public void setCondition(String condition) {
		this.condition = condition;
	}

	public String getValue() {
		return value;
	}

	public void setValue(String value) {
		this.value = value;
	}

	@Override
	public String toString() {
		return "Search [condition=" + condition + ", value=" + value + "]";
	}
	
	
	
	
	
	
}

 

controller.java

실행확인을 하기위한 main class파일

package com.memory2.controller;

import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

import com.memory2.model.service.SelectBuilderService;
import com.memory2.model.service.SqlBuilderService;
import com.memory2.model.vo.Menu;

public class Application {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		
		do {
			System.out.println("======== 구문 빌더 API를 이용한 동적 SQL");
			System.out.println("1. SelectBuilder 테스트하기");
			System.out.println("2. SqlBuilder 테스트 하기");
			System.out.println("9. 프로그램 종료하기");
			System.out.print("메뉴를 입력하세요 : ");
			int no = sc.nextInt();
			
			switch(no) {
			case 1 : selectBuilderTest1(); break;
			case 2 : sqlBuilder(); break;
			}
		} while (true);
	}
	
	private static void selectBuilderTest1() {
		Scanner sc = new Scanner(System.in);
		SelectBuilderService selectBuilderService = new SelectBuilderService();
		
		System.out.println("======== SelsectBuilder 서브 메뉴 =========");
		System.out.println("1. SelectBuilder 기본 구문 사용하기");
		System.out.println("2. SelectBuilder를 이용한 동적 SQL 사용하기");
		System.out.println("9. 이전 메뉴로");
		System.out.print("메뉴를 입력하세요 : ");
		int no = sc.nextInt();
		
		switch(no) {
		case 1 : selectBuilderService.selectMenuAll(); break;
		case 2 : selectBuilderService.selectSqlMenu(inputBuilder()); break;
		case 9 : return;
		default : System.out.println("번호를 다시입력해주세요");
		}
	}
	
	private static Map<String, Object> inputBuilder() {
		Scanner sc = new Scanner(System.in);
		System.out.print("검색 조건을 입력하세요(category or name) : ");
		String condition = sc.nextLine();
		Map<String, Object> returnMap = new HashMap<>();
		
		if(condition.equals("category")) {
			System.out.print("카테고리 번호를 입력해주세요 : ");
			int code = sc.nextInt();
			returnMap.put(condition, code);
		}else if(condition.equals("name")) {
			System.out.print("메뉴명을 입력해주세요 : ");
			String name = sc.nextLine();
			returnMap.put(condition, name);
		}
		
		return returnMap;
	}
	
	private static void sqlBuilder() {
		Scanner sc = new Scanner(System.in);
		SqlBuilderService sqlBuilderService = new SqlBuilderService();
		do {
			System.out.println("======== SqlBuilder 서브 메뉴 =========");
			System.out.println("1. 새로운 메뉴 추가하기");
			System.out.println("2. 기존 메뉴 수정하기");
			System.out.println("3. 마음에 들지 않는 메뉴 삭제하기");
			System.out.println("9. 이전 메뉴로");
			System.out.print("메뉴를 입력하세요 : ");
			int no = sc.nextInt();
			
			switch(no) {
			case 1 : sqlBuilderService.sqlBuilderNewMenu(inputNewInput()); break;
			case 2 : sqlBuilderService.sqlBuildermodfiyMenu(inputModify()); break;
			case 3 : sqlBuilderService.sqlBuilderDeleteMenu(inputDelete()); break;
			}
			
		} while (true);
	}
	
	private static Menu inputNewInput() {
		Scanner sc = new Scanner(System.in);
		System.out.print("등록할 메뉴 이름을 입력하세요 : ");
		String name = sc.nextLine();
		System.out.print("등록할 메뉴 가격을 입력하세요 : ");
		int price = sc.nextInt();
		System.out.print("등록할 카테고리를 입력하세요 : ");
		int categoryCode = sc.nextInt();
		sc.nextLine();
		System.out.print("판매 등록 여부를 입력하세요(Y/N) : ");
		String orderableStatus = sc.nextLine();
		
		Menu menu = new Menu();
		menu.setName(name);
		menu.setPrice(price);
		menu.setCategoryCode(categoryCode);
		menu.setOrderableStatus(orderableStatus);
		
		return menu;
	}
	
	private static Menu inputModify() {
		Scanner sc = new Scanner(System.in);
		
		System.out.print("수정할 메뉴번호를 입력해주세요 : ");
		int code = sc.nextInt();
		System.out.print("수정할 메뉴 이름을 입력하세요 : ");
		sc.nextLine();
		String name = sc.nextLine();
		System.out.print("수정할 메뉴 가격을 입력하세요 : ");
		int price = sc.nextInt();
		System.out.print("수정할 카테고리를 입력하세요 : ");
		int categoryCode = sc.nextInt();
		sc.nextLine();
		System.out.print("수정할 판매 등록 여부를 입력하세요(Y/N) : ");
		String orderableStatus = sc.nextLine();
		
		Menu menu = new Menu();
		menu.setCode(code);
		menu.setName(name);
		menu.setPrice(price);
		menu.setCategoryCode(categoryCode);
		menu.setOrderableStatus(orderableStatus);
		
		return menu;
		
	}
	
	private static int inputDelete() {
		Scanner sc = new Scanner(System.in);
		
		System.out.print("삭제하실 메뉴번호를 입력해주세요 : ");
		return sc.nextInt();
	}
}

 

Template.java

SqlSession 접속객체를 만들기위한 파일

package com.memory2.common;

import java.io.IOException;
import java.io.InputStream;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

public class Template {
	private static SqlSessionFactory sqlSessionFactroy;
	
	public static SqlSession getSqlSession() {
		
		if(sqlSessionFactroy == null) {
			String resource = "config.xml";
			try {
				InputStream inputStream = Resources.getResourceAsStream(resource);
				sqlSessionFactroy = new SqlSessionFactoryBuilder().build(inputStream);
				
			} catch (IOException e) {
				e.printStackTrace();
			}
			
		}
		
		return sqlSessionFactroy.openSession(false);
		
	}
	
	
}

SelectBuilder

(1). SelectBuilder 기본 구문 사용하기

SelectBuilderService.java

// SelectBuilder 서브메뉴 1번
	public void selectMenuAll() {
		SqlSession sqlSession = getSqlSession();
		
		mapper = sqlSession.getMapper(SelectBuilderMapper.class);
		List<Menu> menuList = mapper.selectMenuAll();
		
		if(menuList != null && menuList.size() > 0) {
			for(Menu menu : menuList) {
				System.out.println(menu);
			}
		}else {
			System.out.println("조회된 목록이 존재하지 않습니다.");
		}
		
		sqlSession.close();
		
	}

SelectBuilderMapper.interface

@Results(id = "selectResultMap", value= {
		@Result(id = true, property="code", column="MENU_CODE"),
		@Result(property="name", column="MENU_NAME"),
		@Result(property="price", column="MENU_PRICE"),
		@Result(property="categoryCode", column="CATEGORY_CODE"),
		@Result(property="orderableStatus", column="ORDERABLE_STATUS"),
	})

	@SelectProvider(type=SelectBuilderProvider.class, method="selectMenuAll")
	List<Menu> selectMenuAll();

SelectBuilderProvider.java

public String selectMenuAll() {
		SQL sql = new SQL();
		
		sql.SELECT("MENU_CODE")
		   .SELECT("MENU_NAME")
		   .SELECT("MENU_PRICE")
		   .SELECT("CATEGORY_CODE")
		   .SELECT("ORDERABLE_STATUS")
		   .FROM("TBL_MENU")
		   .WHERE("ORDERABLE_STATUS = 'Y'");
		
		return sql.toString();
	}

 

(2). SelectBuilder를 이용한 동적 SQL 사용하기

SelectBuilderService.java

// SelectBuilder 서브메뉴 2번
	public void selectSqlMenu(Map<String, Object> map) {
		SqlSession sqlSession = getSqlSession();
		
		mapper = sqlSession.getMapper(SelectBuilderMapper.class);
		List<Menu> menuList = mapper.selectSqlMenu(map);
		
		if(menuList != null && menuList.size() > 0) {
			for(Menu menu : menuList) {
				System.out.println(menu);
			}
		}else {
			System.out.println("조회된 목록이 존재하지 않습니다.");
		}
		
		sqlSession.close();
		
		
	}


SelectBuilderMapper.interface

@ResultMap("selectResultMap")
@SelectProvider(type=SelectBuilderProvider.class, method="selectSqlMenu")
List<Menu> selectSqlMenu(Map<String, Object> map);


SelectBuilderProvider.java

public String selectSqlMenu(Map<String, Object> map) {
		SQL sql = new SQL();
		
		sql.SELECT("MENU_CODE")
		   .SELECT("MENU_NAME")
		   .SELECT("MENU_PRICE")
		   .SELECT("CATEGORY_CODE")
		   .SELECT("ORDERABLE_STATUS")
		   .FROM("TBL_MENU");
		
		if(map.containsKey("category")){
			sql.WHERE("CATEGORY_CODE = #{category}");
		}else if(map.containsKey("name")) {
			sql.WHERE("MENU_NAME = #{name}");
		}
		
		sql.ORDER_BY("MENU_CODE");
		return sql.toString();
	}

 

2. SqlBuilder 테스트하기

 (1). 새로운 메뉴 추가하기

SqlBuilderService.java

public void sqlBuilderNewMenu(Menu menu) {
		SqlSession sqlSession = getSqlSession();
		
		mapper = sqlSession.getMapper(SqlBuilderMapper.class);
		
		int result = mapper.newMenu(menu);
		
		if(result > 0) {
			sqlSession.commit();
			System.out.println("새로운 메뉴를 추가하였습니다.");
		}else {
			sqlSession.rollback();
			System.out.println("새로운 메뉴 추가에 실패하였습니다.");
		}
		
		sqlSession.close();
	}


SqlBuilderMapper.java

@InsertProvider(type=SqlBuilderProvider.class, method="newMenu")
	int newMenu(Menu menu);


SqlBuilderProvider.java

public String newMenu(Menu menu) {
		SQL sql = new SQL();
		
		sql.INSERT_INTO("TBL_MENU")
		   .VALUES("MENU_CODE", "SEQ_MENU_CODE.NEXTVAL")
		   .VALUES("MENU_NAME", "#{name}")
		   .VALUES("MENU_PRICE", "#{price}")
		   .VALUES("CATEGORY_CODE", "#{categoryCode}")
		   .VALUES("ORDERABLE_STATUS", "#{orderableStatus}");
		   
		return sql.toString();
	}

 (2). 기존 메뉴 수정하기

SqlBuilderService.java

public void sqlBuildermodfiyMenu(Menu menu) {
		SqlSession sqlSession = getSqlSession();
		
		mapper = sqlSession.getMapper(SqlBuilderMapper.class);
		
		int result = mapper.modifyMenu(menu);
		
		if(result > 0) {
			sqlSession.commit();
			System.out.println("메뉴수정에 성공하였습니다.");
		}else {
			sqlSession.rollback();
			System.out.println("메뉴수정에 실패하였습니다.");
		}
		
		sqlSession.close();
		
	}


SqlBuilderMapper.java

@InsertProvider(type=SqlBuilderProvider.class, method="modifyMenu")
	int modifyMenu(Menu menu);


SqlBuilderProvider.java

public String modifyMenu(Menu menu) {
		SQL sql = new SQL();
		
		sql.UPDATE("TBL_MENU")
		   .SET("MENU_NAME = #{name}", "MENU_PRICE = #{price}", "CATEGORY_CODE = #{categoryCode}", "ORDERABLE_STATUS = #{orderableStatus}")
		   .WHERE("MENU_CODE = #{code}");
		
		return sql.toString();
	}

 

(3). 마음에 들지 않는 메뉴 삭제하기

SqlBuilderService.java

public void sqlBuilderDeleteMenu(int code) {
		SqlSession sqlSession = getSqlSession();
		
		mapper = sqlSession.getMapper(SqlBuilderMapper.class);
		
		int result = mapper.deleteMenu(code);
		
		if(result > 0) {
			sqlSession.commit();
			System.out.println("메뉴삭제에 성공하였습니다.");
		}else {
			sqlSession.rollback();
			System.out.println("메뉴삭제에 실패하였습니다.");
		}
		
		sqlSession.close();
		
	}


SqlBuilderMapper.java

@InsertProvider(type=SqlBuilderProvider.class, method="deleteMenu")
	int deleteMenu(@Param("code")int code);


SqlBuilderProvider.java

public String deleteMenu() {
		SQL sql = new SQL();
		
		sql.DELETE_FROM("TBL_MENU")
		   .WHERE("MENU_CODE = #{code}");
		
		return sql.toString();
	}

 

 

후기

지금까지 Mybatis 학습하면서 제일 깔끔하고 스무스하게 작업한 파트이지 않나싶습니다.

왜냐하면 xml 보다 java 파일로 하니깐 뭔가더 심적으로 편하다고생각되서 ..그렇습니다.

mybatis는 생각보다 할게많고 편의기능이많아서 실무에서 많이 쓰일것같다는생각이들고 

좀더 능숙하게 다뤄야할거같습니다.

 

  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유