myBatis - 5. 동적 쿼리 실습

학원에서 배운내용을 복습할겸 처음부터 다시 쳐보고 코드를 올리는 형식으로 공부진행하고있습니다.

우선 구현할 목차입니다.

 

목차

1. if 확인하기

  (1). 원하는 금액대에 적합한 추천 메뉴 목록 보여주기

  (2). 메뉴 이름 혹은 카테고리 명으로 검색하여 메뉴 목록 보여주기

 

2. choose(when, otherwise) 확인하기

  (1). 카테고리 상위 분류별 메뉴 보여주기(식사, 음료, 디저트)

 

3. foreach 확인하기

  (1). 랜덤한 메뉴 5개 추출해서 조회하기

 

4. trim(where, set) 확인하기

  (1). 검색조건이 있는 경우 메뉴코드로 조회, 단 없으면 전체 조회

  (2). 메뉴 혹은 카테고리코드로 검색, 단 메뉴와 카테고리 둘 다 일치하는 경우도 검색하며, 검색 조건이 없는 경우 전체

  (3). 원하는 메뉴 정보만 수정하기

 

위의 목차로 진행할것입니다.

 

코드 진행방식은 xml + 애너테이션 방식으로 진행할것입니다.

 

공통

template.java

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);
		
	}
	
	
}

 

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>

  <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>
  	<mapper resource="com/memory/model/dao/MenuMapper.xml"/>
  </mappers>
  
</configuration>

 

driver.properties

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

 

menu.java

package com.memory.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.memory.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 + "]";
	}
	
	
	
	
	
	
}

 

Application.java

package com.memory.controller;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Scanner;
import java.util.Set;

import com.memory.model.service.MenuService;
import com.memory.model.vo.Search;

public class Application {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		
		do {
			System.out.println("========= 마이바티스 동적 SQL (조건문) ==========");
			System.out.println("1. if 확인하기");
			System.out.println("2. choose(when, otherwise) 확인하기");
			System.out.println("3. foreach 확인하기");
			System.out.println("4. trim(where, set) 확인하기");
			System.out.println("9. 종료하기");
			System.out.print("메뉴를 선택하세요 : ");
			int no = sc.nextInt();
			
			switch(no) {
			case 1 : showInputIf(); break;
			case 2 : showInputChoose(); break;
			case 3 : showInputForeach(); break;
			case 9 : System.out.println("프로그램을 종료합니다"); break;
			default : System.out.println("존재하지 않는 번호입니다.");
			
			}
			
		}while(true);
		
	}
	
	// 1. if 확인하기
	private static void showInputIf() {
		Scanner sc = new Scanner(System.in);
		MenuService menuService = new MenuService();
		
		do {
			System.out.println("========= if 서브 메뉴 =========");
			System.out.println("1. 원하는 금액대에 적합한 추천 메뉴 목록 보여주기");
			System.out.println("2. 메뉴 이름 혹은 카테고리 명으로 검색하여 메뉴 목록 보여주기");
			System.out.println("9. 이전 메뉴로");
			System.out.print("메뉴 번호를 입력하세요 : ");
			int no = sc.nextInt();
			switch(no) {
				case 1 : menuService.inputIfChoiceMenuList(inputPrice());
				case 2 : menuService.inputIfCateNameMenuList(inputIfSearch());
				case 9 : return;
				default : System.out.println("번호를 다시 입력해주세요!");
			}
			
		}while(true);
	}
	
	private static int inputPrice() {
		Scanner sc = new Scanner(System.in);
		System.out.print("검색하실 가격의 최대 금액을 입력해주세요 : ");
		
		return sc.nextInt();
	}
	
	private static Search inputIfSearch() {
		Scanner sc = new Scanner(System.in);
		
		Search search = new Search();
		
		System.out.print("검색 기준을 입력해주세요(name or category) : ");
		search.setCondition(sc.nextLine());
		
		System.out.print("검색어를 입력해주세요 : ");
		search.setValue(sc.nextLine());
		
		return search;
	}
	
	// 2. choose(when, otherwise) 확인하기
	private static void showInputChoose() {
		Scanner sc = new Scanner(System.in);
		MenuService menuService = new MenuService();
		
		do {
			System.out.println("========= choose =========");
			System.out.println("1. 카테고리 상위 분류별 메뉴 보여주기(식사, 음료, 디저트)");
			System.out.println("9. 이전 메뉴로");
			System.out.print("메뉴 번호를 입력하세요 : ");
			int no = sc.nextInt();
			
			switch(no) {
				case 1 : menuService.categoryTopMenuList(categoryInput()); break;
				case 9 : return;
				default : System.out.println("번호를 다시 입력해주세요!");
			}
			
		}while(true);
	}
	
	private static String categoryInput() {
		Scanner sc = new Scanner(System.in);
		System.out.print("상위 분류를 입력해주세요(식사, 음료, 디저트) : ");
		return sc.nextLine();
	}
	
	// 3. foreach 확인하기
	private static void showInputForeach() {
		Scanner sc = new Scanner(System.in);
		MenuService menuService = new MenuService();
		
		do {
			System.out.println("========= foreach 서브메뉴 =========");
			System.out.println("1. 랜덤한 메뉴 5개 추출해서 조회하기");
			System.out.println("9. 이전 메뉴로");
			System.out.print("메뉴 번호를 입력하세요 : ");
			int no = sc.nextInt();
			
			switch(no) {
				case 1 : menuService.randomMenuList(randomInput()); break;
				case 9 : return;
				default : System.out.println("번호를 다시 입력해주세요!");
			}
			
		}while(true);

	}
	
	private static List<Integer> randomInput(){
		Scanner sc = new Scanner(System.in);
		
		// Set은 중복을 허용하지않기때문에 사용
		Set<Integer> set = new HashSet<>();
		while(set.size() < 5) {
			int num = (int)(Math.random() * 21) + 1;
			set.add(num);
		}
		
		List<Integer> list = new ArrayList<>(set);
		Collections.sort(list); // 정렬
		
		return list;
	}
}

 

1. if 확인하기

(1). 원하는 금액대에 적합한 추천 메뉴 목록 보여주기

MenuService.java

// if 서브메뉴 1번
	public void inputIfChoiceMenuList(int price) {
		SqlSession sqlSession = getSqlSession();
		
		mapper = sqlSession.getMapper(MenuMapper.class);
		
		Map<String, Integer> priceMap = new HashMap<>();
		priceMap.put("price", price);
		
		List<Menu> menuList = mapper.inputIfChoiceMenuList(priceMap);
		
		if(menuList != null && menuList.size() > 0) {
			for(Menu menu : menuList) {
				System.out.println(menu);
			}
		}else {
			System.out.println("조회된 목록이 없습니다.");
		}
		
		sqlSession.close();
	}

 

MenuMapper.interface

// if 서브메뉴 1번
	List<Menu> inputIfChoiceMenuList(Map<String, Integer> priceMap);

 

MenuMapper.xml

<resultMap type="com.memory.model.vo.Menu" id="menuResultMap">
  	<id 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"/>
  </resultMap>

  <select id="inputIfChoiceMenuList" parameterType="hashmap" resultMap="menuResultMap">
  	SELECT
  		   MENU_CODE
  		 , MENU_NAME
  		 , MENU_PRICE
  		 , CATEGORY_CODE
  		 , ORDERABLE_STATUS
      FROM TBL_MENU
     WHERE ORDERABLE_STATUS = 'Y'
     <if test="price &gt;= 0 and price &lt; 10000">
       AND MENU_PRICE BETWEEN 0 AND #{price}
     </if>
     <if test="price &gt;= 10000 and price &lt; 20000">
       AND MENU_PRICE BETWEEN 10000 AND #{price}
     </if>
     <if test="price &gt;= 20000 and price &lt; 30000">
       AND MENU_PRICE BETWEEN 20000 AND #{price}
     </if>
     <if test="price &gt;= 30000 and price &lt; 40000">
       AND MENU_PRICE BETWEEN 30000 AND #{price}
     </if>
     ORDER BY MENU_CODE
  </select>

 

 

(2). 메뉴 이름 혹은 카테고리 명으로 검색하여 메뉴 목록 보여주기

MenuService.java

// if 서브메뉴 2번
	public void inputIfCateNameMenuList(Search inputIfSearch) {
		SqlSession sqlSession = getSqlSession();
		
		mapper = sqlSession.getMapper(MenuMapper.class);
		List<Menu> menuList = mapper.inputIfCateNameMenuList(inputIfSearch);
		
		if(menuList != null & menuList.size() > 0) {
			for(Menu menu : menuList) {
				System.out.println(menu);
			}
		}else {
			System.out.println("조회된 목록이 없습니다.");
		}
		
		sqlSession.close();
		
	}

 

MenuMapper.interface

// if 서브메뉴 2번
	List<Menu> inputIfCateNameMenuList(Search inputIfSearch);

 

MenuMapper.xml

<select id="inputIfCateNameMenuList" parameterType="search" resultMap="menuResultMap">
  	SELECT
  		   MENU_CODE
  		 , MENU_NAME
  		 , MENU_PRICE
  		 , CATEGORY_CODE
  		 , ORDERABLE_STATUS
      FROM TBL_MENU
      <if test="condition == 'category'">
      JOIN TBL_CATEGORY USING(CATEGORY_CODE)
      </if>
     WHERE ORDERABLE_STATUS = 'Y'
     <if test="condition == 'name'">
       AND MENU_NAME LIKE '%' || #{value} || '%'
     </if>
     <if test="condition == 'category'">
       AND CATEGORY_NAME = #{value}
     </if>
  </select>

2. choose(when, otherwise) 확인하기

(1). 카테고리 상위 분류별 메뉴 보여주기(식사, 음료, 디저트)

MenuService.java

// choose 서브메뉴 1번
	public void categoryTopMenuList(String categoryInput) {
		SqlSession sqlSession = getSqlSession();
		
		mapper = sqlSession.getMapper(MenuMapper.class);
		
		Map<String, String> categoryMap = new HashMap<>();
		categoryMap.put("condition", categoryInput);
		
		List<Menu> menuList = mapper.categoryTopMenuList(categoryMap);
		
		if(menuList != null & menuList.size() > 0) {
			for(Menu menu : menuList) {
				System.out.println(menu);
			}
		}else {
			System.out.println("조회된 목록이 없습니다.");
		}
		
		sqlSession.close();
		
		
	}

 

MenuService.java

// choose 서브메뉴 1번
	List<Menu> categoryTopMenuList(Map<String, String> categoryMap);

 

MenuMapper.java

<select id="categoryTopMenuList" parameterType="hashmap" resultMap="menuResultMap">
  	SELECT
  		   MENU_CODE
  		 , MENU_NAME
  		 , MENU_PRICE
  		 , CATEGORY_CODE
  		 , ORDERABLE_STATUS
      FROM TBL_MENU
      WHERE ORDERABLE_STATUS = 'Y'
      <choose>
      	<when test="condition == '식사'">
      	 AND CATEGORY_CODE IN (4, 5, 6, 7)
      	</when>
      	<when test="condition == '음료'">
      	 AND CATEGORY_CODE IN (8, 9, 10)
      	</when>
      	<otherwise>
      	 AND CATEGORY_CODE IN (11, 12)
      	</otherwise>
      </choose>
      ORDER BY MENU_CODE
  </select>

3. foreach 확인하기

(1). 랜덤한 메뉴 5개 추출해서 조회하기

MenuService.java

// foreach 서브메뉴 1번
	public void randomMenuList(List<Integer> randomInput) {
		SqlSession sqlSession = getSqlSession();
		
		mapper = sqlSession.getMapper(MenuMapper.class);
		
		Map<String, List<Integer>> randomMap = new HashMap<>();
		randomMap.put("random", randomInput);
		
		List<Menu> menuList = mapper.randomMenuList(randomMap);
		
		if(menuList != null & menuList.size() > 0) {
			for(Menu menu : menuList) {
				System.out.println(menu);
			}
		}else {
			System.out.println("조회된 목록이 없습니다.");
		}
		
		sqlSession.close();
	}

 

MenuMapper.java

// forEach 서브메뉴 1번
	List<Menu> randomMenuList(Map<String, List<Integer>> randomMap);

 

MenuMapper.xml

<select id="randomMenuList" parameterType="hashmap" resultMap="menuResultMap">
  	SELECT
  		   MENU_CODE
  		 , MENU_NAME
  		 , MENU_PRICE
  		 , CATEGORY_CODE
  		 , ORDERABLE_STATUS
      FROM TBL_MENU
      WHERE ORDERABLE_STATUS = 'Y'
        AND MENU_CODE IN
        <foreach collection="random" item="list" open="(" separator=", " close=")">
        	#{list}
        </foreach>
        ORDER BY MENU_CODE
  </select>

 

 

4. trim 서브 메뉴

(1). 검색조건이 있는 경우 메뉴코드로 조회, 단 없으면 전체 조회

MenuService.java

// trim 서브메뉴 1번
	public void menuTirmWhereSearch(Search search) {
		SqlSession sqlSession = getSqlSession();
		mapper = sqlSession.getMapper(MenuMapper.class);
		
		List<Menu> menuList = mapper.menuTirmWhereSearch(search);
		
		if(menuList != null && menuList.size() > 0) {
			for(Menu menu : menuList) {
				System.out.println(menu);
			}
		}else {
			System.out.println("조회 결과를 찾을수 없습니다.");
		}
		
		sqlSession.close();
		
	}

 

MenuMapper.java

// trim 서브메뉴 1번
	List<Menu> menuTirmWhereSearch(Search search);

 

MenuMapper.xml

<select id="menuTirmWhereSearch" parameterType="search" resultMap="menuResultMap">
  	SELECT
  	       MENU_CODE
  		 , MENU_NAME
  		 , MENU_PRICE
  		 , CATEGORY_CODE
  		 , ORDERABLE_STATUS
      FROM TBL_MENU
      <where>
      	<if test="condition == 'menuCode'">
      		MENU_CODE = #{value}
      	</if>
      </where>
      ORDER BY MENU_CODE
  </select>

 

(2). 메뉴 혹은 카테고리코드로 검색, 단 메뉴와 카테고리 둘 다 일치하는 경우도 검색하며, 검색 조건이 없는 경우 전체 조회

MenuService.java

// trim 서브메뉴 2번
	public void menuTrimChoiceSearch(Map<String, Object> inputChoiceSearch) {
		SqlSession sqlSession = getSqlSession();
		
		mapper = sqlSession.getMapper(MenuMapper.class);
		
		List<Menu> menuList = mapper.menuTrimChoiceSearch(inputChoiceSearch);
		
		if(menuList != null && menuList.size() > 0) {
			for(Menu menu : menuList) {
				System.out.println(menu);
			}
		}else {
			System.out.println("조회 결과를 찾을수 없습니다.");
		}
		
		sqlSession.close();
		
	}

 

MenuMapper.interface

// trim 서브메뉴 2번
	List<Menu> menuTrimChoiceSearch(Map<String, Object> inputChoiceSearch);

MenuMapper.xml

<select id="menuTrimChoiceSearch" parameterType="hashmap" resultMap="menuResultMap">
  	SELECT
  	       MENU_CODE
  		 , MENU_NAME
  		 , MENU_PRICE
  		 , CATEGORY_CODE
  		 , ORDERABLE_STATUS
      FROM TBL_MENU
      <where>
      	<if test="codeValue > 0">
      		AND CATEGORY_CODE = #{codeValue}
      	</if>
      	<if test="nameValue != null">
      		AND MENU_NAME LIKE '%' ||  #{nameValue} || '%'
      	</if>
      </where>
      ORDER BY MENU_CODE
  </select>

 

(3). 3. 원하는 메뉴 정보만 수정하기

MenuService.java

// trim 서브메뉴 3번
	public void menuTrimSetSearch(Menu inputSetSearch) {
		SqlSession sqlSession = getSqlSession();
		
		mapper = sqlSession.getMapper(MenuMapper.class);
		int result = mapper.menuTrimSetSearch(inputSetSearch);
		
		if(result > 0) {
			sqlSession.commit();
			System.out.println("메뉴가 변경되었습니다.");
		}else {
			sqlSession.rollback();
			System.out.println("메뉴가 변경 실패하였습니다..");
		}
		
		sqlSession.close();
	}

 

MenuMapper.interface

// trime 서브메뉴 3번
	int menuTrimSetSearch(Menu inputSetSearch);

 

MenuMapper.xml

<update id="menuTrimSetSearch" parameterType="com.memory.model.vo.Menu">
  	UPDATE 
  	       TBL_MENU
  	      <set>
  	      	<if test="name != null and name != ''">
  	      		MENU_NAME = #{name},
  	      	</if>
  	      	<if test="code > 0">
  	      		CATEGORY_CODE = #{categoryCode},
  	      	</if>
  	      	<if test="orderableStatus != null and orderableStatus != ''">
  	      		ORDERABLE_STATUS = #{orderableStatus},
  	      	</if>
  	      </set>
  	 WHERE MENU_CODE = #{code}
  </update>

 

 

실습후기

애너테이션에 쿼리문을 작성하지않아도되서 .. 가독성이 올라간것같고 mybatis 사용안할땐 다중검색이 dao 에 ..구문이너무 지저분했었는데 .. 동적 배우고난후. 코드가 한결 깔끔해지고 코드 작성시간이 많이 단축된것같습니다.

다음시간은 SQL빌더 클래스 이용해서 작성하는법을 배울예정입니다.

SQL 클래스 이용하여 더간결하게 가독성있고 더편하게 할수있는방법인거같습니다 .

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