본문 바로가기
Java/└ [JDBC] Practice

[실습문제] JDBC 종합

by 박채니 2022. 5. 10.

안녕하세요, 코린이의 코딩 학습기 채니 입니다.

 

개인 포스팅용으로 내용에 오류 및 잘못된 정보가 있을 수 있습니다.


@실습문제 : jdbc종합
상품재고관리프로그램을 작성하세요.

전체상품조회결과
----------------------------------------------------------------------------------------------------
id                brand        name            price            spec                            stock
----------------------------------------------------------------------------------------------------
14TD90P-GX30K    LG전자         그램360          1,046,990원     15인치 / Windows10 / 256GB        55
X413EA-EB086    ASUS         비보북             609,000원        14인치 / Windows10 / 256GB         30
16ACH-R7-STORM    Lenovo        LEGION 5 Pro     1,699,000원        16인치 / Windows10 / 512GB         30
MVVK2KH/A        Apple        맥북프로          3,705,690원       16인치 / macOS / 512GB             10
----------------------------------------------------------------------------------------------------

메인메뉴

***** 상품 재고관리 프로그램 *****
1. 전체상품조회
2. 상품검색
3. 상품등록
4. 상품정보변경
5. 상품삭제
6. 상품입/출고 메뉴
0. 프로그램종료
********************************


검색메뉴
- 아이디/상품명 모두 문자열일부 검색이 가능해야 한다.

***** 상품검색 메뉴 *****
1.아이디 검색
2.상품명 검색
0.메인메뉴로 돌아가기

수정메뉴

***** 상품정보 변경 메뉴 *****
1.상품명변경
2.가격변경
3.사양변경
0.메인메뉴로 돌아가기

입출고메뉴
- 각 메뉴선택시 현재상품목록 출력하고, 선택할 수 있어야 한다. (아이디가 아닌 번호를 입력해서 선택)
- 입출고내역조회시 특정상품의 최근 입출고내역을 조회(입출고번호, 상품id, 상품명(브랜드), 수량, 입출고여부, 입출고시각)

***** 상품입출고 메뉴*****
1. 입출고내역조회
2. 상품입고
3. 상품출고
0. 메인메뉴로 돌아가기

* 상품정보를 삭제하면, 해당 입출고 데이터도 삭제되도록 처리.
* 입고된 수량보다 많은 수량을 출고시, 에러메세지를 보이고, 출고처리가 되어서는 안됨.
* 상품입출고테이블에 데이터가 삽입될때마다, 자동으로 재고테이블의 수량이 변경될 수 있도록 트리거를 작성할것.

상품 상세테이블 PRODUCT
* ID  VARCHAR2(30) PRIMARY KEY
* BRAND VARCHAR2(50) NOT NULL    
* NAME  VARCHAR2(30)  NOT NULL
* PRICE NUMBER(10)  NOT NULL
* MONITOR_SIZE NUMBER
* OS VARCHAR2(100)
* STORAGE NUMBER
* STOCK NUMBER DEFAULT 0 CHECK(STOCK >= 0)
* REG_DATE DATE DEFAULT SYSDATE

상품입출고 테이블 PRODUCT_IO
* NO NUMBER PRIMARY KEY => SEQUENCE 처리할 것.
* PRODUCT_ID VARCHAR2(30) => PRODUCT테이블 ID 참조
* COUNT NUMBER CHECK 
* STATUS CHAR(1) CHECK (STATUS IN ('I', 'O'))
* IO_DATETIME TIMESTAMP DEFAULT SYSTIMESTAMP


Product(VO)

package product.model.vo;

import java.sql.Date;

public class Product {
	private int no;
	private String id;
	private String brand;
	private String name;
	private int price;
	private int monitorSize;
	private String os;
	private int storage;
	private int stock;
	private Date regDate;
	
	public Product() {
		super();
	}

	public Product(int no, String id, String brand, String name, int price, int monitorSize, String os, int storage, int stock,
			Date regDate) {
		super();
		this.no = no;
		this.id = id;
		this.brand = brand;
		this.name = name;
		this.price = price;
		this.monitorSize = monitorSize;
		this.os = os;
		this.storage = storage;
		this.stock = stock;
		this.regDate = regDate;
	}
	
	

	public int getNo() {
		return no;
	}

	public void setNo(int no) {
		this.no = no;
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getBrand() {
		return brand;
	}

	public void setBrand(String brand) {
		this.brand = brand;
	}

	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 getMonitorSize() {
		return monitorSize;
	}

	public void setMonitorSize(int monitorSize) {
		this.monitorSize = monitorSize;
	}

	public String getOs() {
		return os;
	}

	public void setOs(String os) {
		this.os = os;
	}

	public int getStorage() {
		return storage;
	}

	public void setStorage(int storage) {
		this.storage = storage;
	}

	public int getStock() {
		return stock;
	}

	public void setStock(int stock) {
		this.stock = stock;
	}

	public Date getRegDate() {
		return regDate;
	}

	public void setRegDate(Date regDate) {
		this.regDate = regDate;
	}

	@Override
	public String toString() {
		return "Product [id=" + id + ", brand=" + brand + ", name=" + name + ", price=" + price + ", monitorSize="
				+ monitorSize + ", os=" + os + ", storage=" + storage + ", stock=" + stock + ", regDate=" + regDate
				+ "]";
	}
}

 

ProductIO(VO)

package product.model.vo;

import java.sql.Timestamp;

public class ProductIO {
	private int no;
	private String productId;
	private int count;
	private String status;
	private Timestamp ioDateTime;
	
	
	public ProductIO() {
		super();
	}

	public ProductIO(int no, String product_id, int count, String status, Timestamp ioDateTime) {
		super();
		this.no = no;
		this.productId = product_id;
		this.count = count;
		this.status = status;
		this.ioDateTime = ioDateTime;
	}

	public int getNo() {
		return no;
	}

	public void setNo(int no) {
		this.no = no;
	}

	public String getProductId() {
		return productId;
	}

	public void setProduct_id(String productId) {
		this.productId = productId;
	}

	public int getCount() {
		return count;
	}

	public void setCount(int count) {
		this.count = count;
	}

	public String getStatus() {
		return status;
	}

	public void setStatus(String status) {
		this.status = status;
	}

	public Timestamp getIoDateTime() {
		return ioDateTime;
	}

	public void setIoDateTime(Timestamp ioDateTime) {
		this.ioDateTime = ioDateTime;
	}

	@Override
	public String toString() {
		return "ProductIO [no=" + no + ", productId=" + productId + ", count=" + count + ", status=" + status
				+ ", ioDateTime=" + ioDateTime + "]";
	}
}

 

JdbcTemplate

package product.common;

import java.io.FileReader;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Properties;

public class JdbcTemplate {
	
	static String driverClass;
	static String url; // db접속프로토콜@ip:포트:db명(sid)
	static String user;
	static String password;
	
	static {
		Properties prop = new Properties();
		try {
			prop.load(new FileReader("resource/datasource.properties"));
			driverClass = prop.getProperty("driverClass");
			url = prop.getProperty("url");
			user = prop.getProperty("user");
			password = prop.getProperty("password");
		} catch (IOException e1) {
			e1.printStackTrace();
		}
		
		
		try {
			Class.forName(driverClass);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
	
	// Connection 객체 생성
	public static Connection getConnection() {
		Connection conn = null;
		try {
			 conn = DriverManager.getConnection(url, user, password);
			 conn.setAutoCommit(false);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return conn;
	}
	
	// close
	public static void close(ResultSet rset) {
		try {
			rset.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public static void close(PreparedStatement pstmt) {
		try {
			pstmt.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public static void close(Connection conn) {
		try {
			conn.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	// 트랜잭션
	public static void commit(Connection conn) {
		try {
			conn.commit();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public static void rollback(Connection conn) {
		try {
			conn.rollback();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

 

ProductRun(Run)

package product.run;

import product.view.ProductMenu;

public class ProductRun {
	
	public static void main(String[] args) {
		new ProductMenu().mainMenu();
		System.out.println("🎈이용해주셔서 감사합니다🎈");
	}
}

 

ProductMenu(View)

package product.view;

import java.text.DecimalFormat;
import java.util.List;
import java.util.Scanner;

import product.controller.ProductController;
import product.model.vo.Product;
import product.model.vo.ProductIO;

public class ProductMenu {
	
	private Scanner sc = new Scanner(System.in);
	private ProductController productController = new ProductController();
	
	private int result = 0;
	private List<Product> products = null;
	private Product product = null;
	private String id = null;
	private List<ProductIO> productsIO = null;
	private DecimalFormat numFormat = new DecimalFormat("###,###");
	
	public void mainMenu() {
		String menu = "\n=============================\n"
					+ "🎁 상 품 재 고 관 리 프 로 그 램 🎁\n"
					+ "=============================\n"
					+ "1. 전체 상품 조회\n"
					+ "2. 상품 검색\n"
					+ "3. 상품 등록\n"
					+ "4. 상품 정보 변경\n"
					+ "5. 상품 삭제\n"
					+ "6. 상품 입/출고 메뉴\n"
					+ "0. 프로그램 종료\n"
					+ "-----------------------------\n"
					+ "번호 선택 → ";
		
		while(true) {
			System.out.print(menu);
			String input = sc.next();

			switch(input) {
			case "1" : 
				products = productController.findAll();
				printProducts(products);
				break;
			case "2" :
				findByIdOrProductName();
				break;
			case "3" :
				product = inputProduct();
				result = productController.insertProduct(product);
				displayResult(result, "상품 등록");
				break;
			case "4" :
				updateProduct();
				break;
			case "5" :
				printProducts(productController.findAll());
				id = searchId();
				result = productController.deleteProduct(id);
				displayResult(result, "상품 삭제");
				break;
			case "6" :
				IOAboutProduct();
				break;
			case "0" : return;
			default : System.out.println("잘못 입력하셨습니다. 다시 입력해주세요.");
			}
		}
	}

	// 여러 상품 조회
	private void printProducts(List<Product> products) {
		if(products != null && !products.isEmpty()) {
			System.out.println("=================================================================================");
			System.out.println(" 	                           🎁 상 품 조 회 결 과 🎁                         ");
			System.out.println("=================================================================================");
			System.out.printf("%-5s%-18s%-10s%-10s%-10s%-15s%-8s\n", "no", "id", "brand", "name", "price", "spec", "stock");
			System.out.println("--------------------------------------------------------------------------------");
			
			for(Product product : products) {
				System.out.printf("%-5s%-18s%-8s%-10s%s원  %s인치/%s/%sGB%5s\n",
									product.getNo(),
									product.getId(),
									product.getBrand(),
									product.getName(),
									numFormat.format(product.getPrice()),
									product.getMonitorSize(),
									product.getOs(),
									product.getStorage(),
									product.getStock()
								);
			}
			System.out.println("--------------------------------------------------------------------------------");
		} else System.out.println("> 조회 결과가 없습니다. 상품을 등록해주세요.");
	}
	
	// 한 상품 조회
	private void printProduct(Product product) {
		if(product != null) {
			System.out.println("=================================================================================");
			System.out.println(" 	                           🎁 상 품 조 회 결 과 🎁                         ");
			System.out.println("=================================================================================");
			System.out.printf("%-5s%-18s%-10s%-10s%-10s%-15s%-8s\n", "no", "id", "brand", "name", "price", "spec", "stock");
			System.out.println("--------------------------------------------------------------------------------");
		
			System.out.printf("%-5s%-18s%-8s%-10s%s원  %s인치/%s/%sGB%5s\n",
					product.getNo(),
					product.getId(),
					product.getBrand(),
					product.getName(),
					numFormat.format(product.getPrice()),
					product.getMonitorSize(),
					product.getOs(),
					product.getStorage(),
					product.getStock()
			);
			System.out.println("--------------------------------------------------------------------------------");
		} else	System.out.println("> 조회 결과가 없습니다. 상품을 등록해주세요.");
	}
	
	// 아이디 검색
	private String searchId() {
		System.out.print("> 상품의 ID를 입력하세요 → ");
		return sc.next().toUpperCase();
	}
	
	// 아이디 조회인지 상품명 검색인지
	private void findByIdOrProductName() {
		String menu = "\n----------------------------------------------------------------\n"
					+ "                    🎁 상 품 검 색 메 뉴 🎁                         \n"
					+ "----------------------------------------------------------------\n"
					+ "1. 아이디 검색\n"
					+ "2. 상품명 검색\n"
					+ "0. 메인 메뉴로 돌아가기\n"
					+ "----------------------------------------------------------------\n"
					+ "번호 선택 → ";
		
		String find = null;
		String type = null;
		
		while(true) {
			System.out.print(menu);
			String input = sc.next();
			
			switch(input) {
			case "1" : 
				find = searchId();	
				type = "id";
				break;
			case "2" : 
				System.out.print("> 상품의 상품명을 입력하세요 → ");
				find = sc.next();		
				type = "name";
				break;
			case "0" : return;
			default : System.out.println("잘못 입력하셨습니다. 다시 입력하세요."); continue;
			}
			printProduct(productController.findByIdOrProductName(type, find));
		}
	}

	// 상품 등록
	private Product inputProduct() {
		Product product = new Product();
		
		while(true) {
			String id = searchId();
			
			// 중복 체크
			if(productController.findById(id) == null) {
				System.out.printf("[%s]는 등록 가능한 상품입니다 :)\n", id);
				product.setId(id);
				break;
			}
			else System.out.printf("[%s]는 이미 등록된 상품입니다. 다른 상품을 입력해주세요.\n", id);
		}
			
		System.out.print("> 상품의 브랜드를 입력하세요 → ");
		product.setBrand(sc.next());
		System.out.print("> 상품의 이름을 입력하세요 → ");
		product.setName(sc.next());
		System.out.print("> 상품의 가격을 입력하세요(ex.1000000) → ");
		product.setPrice(sc.nextInt());
		System.out.print("> 상품의 모니터 크기를 입력하세요(ex.15) → ");
		product.setMonitorSize(sc.nextInt());
		System.out.print("> 상품의 운영체제를 입력하세요 → ");
		product.setOs(sc.next());
		System.out.print("> 상품의 용량을 입력하세요(ex.256) → ");
		product.setStorage(sc.nextInt());
			
		return product;
	}
	
	// 상품 변경
	private void updateProduct() {
		String menu = "\n----------------------------------------------------------------\n"
				+ "                    🎁 상 품 변 경 메 뉴 🎁                         \n"
				+ "----------------------------------------------------------------\n"
				+ "1. 상품명 변경\n"
				+ "2. 가격 변경\n"
				+ "3. 사양 변경\n"
				+ "0. 메인 메뉴로 돌아가기\n"
				+ "----------------------------------------------------------------\n"
				+ "번호 선택 → ";
		
		String id = null;
		
		while(true) {
			// 전체 상품 출력
			printProducts(productController.findAll());
			System.out.print("> 변경할 상품의 NO을 입력하세요 → ");
			id = productController.findByNo(sc.nextInt());
			
			if(productController.findById(id) == null) 
				System.out.println("> 존재하지 않는 아이디입니다. 정확하게 입력해주세요.");
			else break;
		}
		
		while(true) {
			System.out.print(menu);
			String input = sc.next();
			
			String type = null;
			Object updateVal = null;
			
			printProduct(productController.findById(id));
			
			switch(input) {
			case "1" :
				System.out.print("> 변경하실 상품명을 입력하세요 → ");
				updateVal = sc.next();
				type = "name";
				break;
			case "2" :
				System.out.print("> 변경하실 가격을 입력하세요 → ");
				updateVal = sc.next();
				type = "price";
				break;
			case "3" :
				System.out.print("> 변경하실 사양을 입력하세요 → ");
				updateVal = sc.next();
				type = "storage";
				break;
			case "0" : return;
			default : System.out.println("잘못 입력하셨습니다. 다시 입력하세요.");
			}
			displayResult(productController.updateProduct(id, type, updateVal), "정보 변경");
			printProduct(productController.findById(id));
		}
	}
	
	// 상품 입출고메뉴
	private void IOAboutProduct() {
		String menu = "\n----------------------------------------------------------------\n"
				+ "                    🎁 상 품 입 출 고 메 뉴 🎁                         \n"
				+ "----------------------------------------------------------------\n"
				+ "1. 입출고 내역 조회\n"
				+ "2. 상품 입고\n"
				+ "3. 상품 출고\n"
				+ "0. 메인 메뉴로 돌아가기\n"
				+ "----------------------------------------------------------------\n"
				+ "번호 선택 → ";
		
		while(true) {
			System.out.print(menu);
			String input = sc.next();
			
			// 상품 리스트 조회
			printProducts(productController.findAll());
			
			String type = null;
			String id = null;
			int count = 0;
			
			switch(input) {
			case "1" :
				productsIO = productController.findAllAboutProductIO();
				printProductsIO(productsIO);
				break;
			case "2" :
				while(true) {
					System.out.print("> 입고할 상품의 NO를 입력해주세요 → ");
					id = productController.findByNo(sc.nextInt());
					if(productController.findById(id) == null) {
						System.out.println("> 존재하지 않는 NO입니다. 다시 입력해주세요.");
					}
					else break;
				}
				System.out.print("> 상품의 입고 개수를 입력해주세요(ex.10) → ");
				count = sc.nextInt();
				type = "I";
				result = productController.cancelProductIO(id, count, type);
				displayResult(result, "상품 입고");
				break;
			case "3" :
				while(true) {
					System.out.print("> 출고할 상품의 NO를 입력해주세요 → ");
					id = productController.findByNo(sc.nextInt());
					if(productController.findById(id) == null) {
						System.out.println("> 존재하지 않는 NO입니다. 다시 입력해주세요.");
					}
					else break;
				}
				System.out.print("> 상품의 출고 개수를 입력해주세요(ex.10) → ");
				count = sc.nextInt();
				type = "O";
				result = productController.cancelProductIO(id, count, type);
				displayResult(result, "상품 출고");
				break;
			case "0" : return;
			default : System.out.println("> 잘못 입력하셨습니다. 다시 입력해주세요.");
			}
			
		}
	}
	
	// 상품 입출고 내역 조회
	private void printProductsIO(List<ProductIO> productsIO) {
		if(productsIO != null && !productsIO.isEmpty()) {
			System.out.println("================================================================");
			System.out.println("                    🎁 입 출 고 내 역 조 회 🎁                         ");
			System.out.println("================================================================");
			System.out.printf("%-5s%-20s%-10s%-10s%-10s\n", "no", "productId", "count", "status", "IODate");
			System.out.println("----------------------------------------------------------------");
		
			for(ProductIO productIO : productsIO) {
				System.out.printf("%-5s%-20s%-10s%-10s%-10s\n",
							productIO.getNo(),
							productIO.getProductId(),
							productIO.getCount(),
							productIO.getStatus(),
							productIO.getIoDateTime()
						);
			}
			System.out.println("----------------------------------------------------------------");
		} else System.out.println("> 조회 결과가 없습니다. 상품을 등록해주세요.");
	}

	private void displayResult(int result, String string) {
		if(result > 0) 
			System.out.println("> " + string + " 성공!");
		else 
			System.out.println("> " + string + " 실패!");
	}
	
	public static void displayError(String msg) {
		System.err.println("> 오류가 발생했습니다. 관리자에게 연락해주세요 : " + msg);
	}
	
	public static void displayErrorClient(String msg) {
		System.err.println("> " + msg);
	}
}

 

ProductController

package product.controller;
import static product.view.ProductMenu.*;
import java.util.List;

import product.model.exception.ProductStockNotCheckException;
import product.model.exception.ProductStockNumUnderZero;
import product.model.service.ProductService;
import product.model.vo.Product;
import product.model.vo.ProductIO;

public class ProductController {
	
	private ProductService productService = new ProductService();
	
	// 전체 상품 조회
	public List<Product> findAll() {
		List<Product> products = null;
		try {
			products = productService.findAll();
		} catch(Exception e) {
			displayError(e.getMessage());
		}
		return products;
	}
	
	// 상품 검색
	public Product findByIdOrProductName(String type, String find) {
		Product product = null;
		try {
			product = productService.findByIdOrProductName(type, find);
		} catch(Exception e) {
			displayError(e.getMessage());
		}
		return product;
	}
	
	// 상품 등록
	public int insertProduct(Product product) {
		int result = 0;
		try {
			result = productService.insertProduct(product);
		} catch(Exception e) {
			displayError(e.getMessage());
		}
		return result; 
	}
	
	// 상품 아이디 조회
	public Product findById(String id) {
		Product product = null;
		try {
			product = productService.findById(id);
		} catch(Exception e) {
			displayError(e.getMessage());
		}
		return product;
	}
	
	// 상품 정보 변경
	public int updateProduct(String id, String type, Object updateVal) {
		int result = 0;
		try {
			result =  productService.updateProduct(id, type, updateVal);
		} catch(Exception e) {
			displayError(e.getMessage());
		}
		return result;
	}
	
	// 상품 삭제
	public int deleteProduct(String id) {
		int result = 0;
		try {
			result = productService.deleteProduct(id);
		} catch(Exception e) {
			displayError(e.getMessage());
		}
		return result; 
	}
	
	// 상품 입출고 내역 조회
	public List<ProductIO> findAllAboutProductIO() {
		List<ProductIO> productsIO = null;
		try {
			productsIO = productService.findAllAboutProductIO();
		} catch(Exception e) {
			displayError(e.getMessage());
		}
		return productsIO; 
	}
	
	// 상품 NO로 ID찾기
	public String findByNo(int no) {
		String id = null;
		try {
			id = productService.findByNo(no);
		} catch(Exception e) {
			displayError(e.getMessage());
		}
		return id; 
	}
	
	// 상품 입고
	public int insertProductIO(String id, int count, String type) {
		int result = 0;
		try {
			result = productService.insertProductIO(id, count, type);
		} catch(ProductStockNumUnderZero e) {
			displayErrorClient(e.getMessage());
		}
		catch(Exception e) {
			displayError(e.getMessage());
		}
		return result;
	}
	
	// 상품 출고
	public int cancelProductIO(String id, int count, String type) {
		int result = 0;
		try {
			result = productService.cancelProductIO(id, count, type);
		} catch(ProductStockNotCheckException e) {
			displayErrorClient(e.getMessage());
		} catch(Exception e) {
			displayError(e.getMessage());
		}
		return result;
	}
}

 

ProductService

package product.model.service;

import static product.common.JdbcTemplate.close;
import static product.common.JdbcTemplate.commit;
import static product.common.JdbcTemplate.getConnection;
import static product.common.JdbcTemplate.rollback;

import java.sql.Connection;
import java.util.List;

import product.model.dao.ProductDao;
import product.model.vo.Product;
import product.model.vo.ProductIO;
public class ProductService {
	private ProductDao productDao = new ProductDao();
	
	// 전체 상품 조회
	public List<Product> findAll() {
		Connection conn = getConnection();
		List<Product> products = productDao.findAll(conn);
		close(conn);
		return products;
	}
	
	// 상품 검색
	public Product findByIdOrProductName(String type, String find) {
		Connection conn = getConnection();
		Product product = productDao.findByIdOrProductName(conn, type, find);
		close(conn);
		return product;
	}
	
	
	// 상품 아이디 검색
	public Product findById(String id) {
		Connection conn = getConnection();
		Product product = productDao.findById(conn, id);
		close(conn);
		return product;
	}
	
	// 상품 등록
	public int insertProduct(Product product) {
		Connection conn = null;
		int result = 0;
		try {
			conn = getConnection();
			result = productDao.insertProduct(conn, product);
			commit(conn);
		} catch(Exception e) {
			rollback(conn);
			throw e;
		} finally {
			close(conn);
		}
		return result;
	}
	
	// 상품 정보 변경
	public int updateProduct(String id, String type, Object updateVal) {
		Connection conn = null;
		int result = 0;
		
		try {
			conn = getConnection();
			result = productDao.updateProduct(conn, id, type, updateVal);
			commit(conn);
		} catch(Exception e) {
			rollback(conn);
			throw e;
		} finally {
			close(conn);
		}
		return result;
	}
	
	// 상품 삭제
	public int deleteProduct(String id) {
		Connection conn = null;
		int result = 0;
		
		try {
			conn = getConnection();
			result = productDao.deleteProduct(conn, id);
			commit(conn);
		} catch(Exception e) {
			rollback(conn);
			throw e;
		} finally {
			close(conn);
		}
		return result;
	}
	
	// 상품 입출고 조회
	public List<ProductIO> findAllAboutProductIO() {
		Connection conn = getConnection();
		List<ProductIO> productsIO = productDao.findAllAboutProductIO(conn);
		close(conn);
		return productsIO;
	}
	
	// 상품 NO로 ID찾기
	public String findByNo(int no) {
		Connection conn = getConnection();
		String id = productDao.findByNO(conn, no);
		close(conn);
		return id;
	}
	
	// 상품 입고
	public int insertProductIO(String id, int count, String type) {
		Connection conn = null;
		int result = 0;
		try {
			conn = getConnection();
			result = productDao.insertProductIO(conn, id, count, type);
			commit(conn);
		} catch(Exception e) {
			rollback(conn);
			throw e;
		} finally {
			close(conn);
		}
		return result;
	}
	
	// 상품 출고
	public int cancelProductIO(String id, int count, String type) {
		Connection conn = null;
		int result = 0;
		try {
			conn = getConnection();
			result = productDao.cancelProductIO(conn, id, count, type);
			commit(conn);
		} catch(Exception e) {
			rollback(conn);
			throw e;
		} finally {
			close(conn);
		}
		return result;
	}

}

 

ProductDao

package product.model.dao;

import static product.common.JdbcTemplate.close;

import java.io.FileReader;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import product.model.exception.ProductException;
import product.model.exception.ProductStockNotCheckException;
import product.model.exception.ProductStockNumUnderZero;
import product.model.vo.Product;
import product.model.vo.ProductIO;

public class ProductDao {
	
	private Properties prop;
	
	public ProductDao() {
		prop = new Properties();
		try {
			prop.load(new FileReader("resource/product-sql.properties"));
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	// 전체 상품 조회
	public List<Product> findAll(Connection conn) {
		List<Product> products = new ArrayList<>();
		PreparedStatement pstmt = null;
		ResultSet rset = null;
		String sql = prop.getProperty("findAll");
		
		try {
			pstmt = conn.prepareStatement(sql);
			rset = pstmt.executeQuery();
			while(rset.next()) {
				products.add(productResultSet(rset));
			}
		} catch (Exception e) {
			throw new ProductException("상품 전체 조회 오류!", e);
		} finally {
			close(rset);
			close(pstmt);
		}
		return products;
	}
	
	// 상품 검색
	public Product findByIdOrProductName(Connection conn, String type, String find) {
		PreparedStatement pstmt = null;
		ResultSet rset = null;
		Product product = null;
		String sql = prop.getProperty("findByIdOrProductName");
		
		try {
			sql = sql.replace("%", type);
			pstmt = conn.prepareStatement(sql);
			pstmt.setString(1, "%" + find + "%");
			rset = pstmt.executeQuery();
			while(rset.next()) {
				product = productResultSet(rset);
			}
		} catch (SQLException e) {
			throw new ProductException("상품 검색 오류 발생!", e);
		} finally {
			close(rset);
			close(pstmt);
		}
		return product;
	}
	
	// 상품 아이디 검색
	public Product findById(Connection conn, String id) {
		PreparedStatement pstmt = null;
		ResultSet rset = null;
		Product product = null;
		String sql = prop.getProperty("findById");
				
		try {
			pstmt = conn.prepareStatement(sql);
			pstmt.setString(1, id);
			rset = pstmt.executeQuery();
			while(rset.next()) {
				product = productResultSet(rset);
			}
		} catch (Exception e) {
			throw new ProductException("상품 아이디 검색 오류 발생!", e);
		} finally {
			close(rset);
			close(pstmt);
		}
		return product;
	}
	
	// 상품 등록
	public int insertProduct(Connection conn, Product product) {
		PreparedStatement pstmt = null;
		int result = 0;
		String sql = prop.getProperty("insertProduct");
		
		try {
			pstmt = conn.prepareStatement(sql);
			pstmt.setString(1, product.getId());
			pstmt.setString(2, product.getBrand());
			pstmt.setString(3, product.getName());
			pstmt.setInt(4, product.getPrice());
			pstmt.setInt(5, product.getMonitorSize());
			pstmt.setString(6, product.getOs());
			pstmt.setInt(7, product.getStorage());
			result = pstmt.executeUpdate();
		} catch (Exception e) {
			throw new ProductException("상품 등록 오류 발생!", e);
		} finally {
			close(pstmt);
		}
		return result;
	}
	
	// 상품 정보 변경
	public int updateProduct(Connection conn, String id, String type, Object updateVal) {
		PreparedStatement pstmt = null;
		int result = 0;
		String sql = prop.getProperty("updateProduct");
		
		try {
			sql = sql.replace("%", type);
			pstmt = conn.prepareStatement(sql);
			pstmt.setObject(1, updateVal);
			pstmt.setString(2, id);
			result = pstmt.executeUpdate();
		} catch (Exception e) {
			throw new ProductException("상품 정보 변경 오류 발생!", e	);
		} finally {
			close(pstmt);
		}
		return result;
	}

	// 상품 삭제
	public int deleteProduct(Connection conn, String id) {
		PreparedStatement pstmt = null;
		int result = 0;
		String sql = prop.getProperty("deleteProduct");
		
		try {
			pstmt = conn.prepareStatement(sql);
			pstmt.setString(1, id);
			result = pstmt.executeUpdate();
		} catch (Exception e) {
			throw new ProductException("상품 삭제 오류 발생!", e);
		} finally {
			close(pstmt);
		}
		return result;
	}
	
	// 상품 입출고 내역 조회
	public List<ProductIO> findAllAboutProductIO(Connection conn) {
		PreparedStatement pstmt = null;
		ResultSet rset = null;
		List<ProductIO> productsIO = new ArrayList<>();
		String sql = prop.getProperty("findAllAboutProductIO");
		
		try {
			pstmt = conn.prepareStatement(sql);
			rset = pstmt.executeQuery();
			while(rset.next()) {
				productsIO.add(productIOResultSet(rset));
			}
		} catch (Exception e) {
			throw new ProductException("상품 입출고 내역 조회 오류 발생!", e);
		}
		return productsIO;
	}
	
	// 상품 NO로 ID찾기
	public String findByNO(Connection conn, int no) {
		PreparedStatement pstmt = null;
		String id = null;
		ResultSet rset = null;
		String sql = prop.getProperty("findByNO"); 
				
		try {
			pstmt = conn.prepareStatement(sql);
			pstmt.setInt(1, no);
			rset = pstmt.executeQuery();
			while(rset.next()) {
				id = rset.getString("id");
			}
		} catch (Exception e) {
			throw new ProductException("상품 번호 아이디 찾기 오류 발생!", e);
		} finally {
			close(rset);
			close(pstmt);
		}
		return id;
	}

	
	// 상품 입고
	public int insertProductIO(Connection conn, String id, int count, String type) {
		PreparedStatement pstmt = null;
		int result = 0;
		String sql = prop.getProperty("insertProductIO");
				
		try {
			pstmt = conn.prepareStatement(sql);
			pstmt.setString(1, id);
			pstmt.setInt(2, count);
			pstmt.setString(3, type);
			result = pstmt.executeUpdate();
		} catch (Exception e) {
			if(count < 0) 
				throw new ProductStockNumUnderZero("오류 발생! : 0개 이상의 재고 수량을 입력해주세요.");
			else
				throw new ProductException("상품 입고 오류 발생!", e);
		} finally {
			close(pstmt);
		}
		return result;
	}
	
	// 상품 출고
	public int cancelProductIO(Connection conn, String id, int count, String type) {
		PreparedStatement pstmt = null;
		int result = 0;
		String sql = prop.getProperty("cancelProductIO");
				
		try {
			pstmt = conn.prepareStatement(sql);
			pstmt.setString(1, id);
			pstmt.setInt(2, count);
			pstmt.setString(3, type);
			result = pstmt.executeUpdate();
		} catch(Exception e) {
			if(e.getMessage().contains("PRODUCT.CK_PRODUCT_STOCK")) 
				throw new ProductStockNotCheckException("재고 부족 오류 발생!", e);
			else 
				throw new ProductException("상품 출고 오류 발생!", e	);
		} finally {
			close(pstmt);
		}
		return result;
	}
	
	public Product productResultSet(ResultSet rset) {
		Product product = new Product();
		try {
			product.setNo(rset.getInt("no"));
			product.setId(rset.getString("id"));
			product.setBrand(rset.getString("brand"));
			product.setName(rset.getString("name"));
			product.setPrice(rset.getInt("price"));
			product.setMonitorSize(rset.getInt("monitor_size"));
			product.setOs(rset.getString("os"));
			product.setStorage(rset.getInt("storage"));
			product.setStock(rset.getInt("stock"));
			product.setRegDate(rset.getDate("reg_date"));
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return product;
	}
	
	public ProductIO productIOResultSet(ResultSet rset) {
		ProductIO productIO = new ProductIO();
		try {
			productIO.setNo(rset.getInt("no"));
			productIO.setProduct_id(rset.getString("product_id"));
			productIO.setCount(rset.getInt("count"));
			productIO.setStatus(rset.getString("status"));
			productIO.setIoDateTime(rset.getTimestamp("io_datetime"));
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return productIO;
	}
}

 

############### datasource.properties ###############
driverClass = oracle.jdbc.OracleDriver
url = jdbc:oracle:thin:@localhost:1521:xe
user = product
password = 비번

 

############### product-sql.properties ###############
findAll = select * from (select rownum no, p.* from (select * from product order by reg_date) p) p
findByIdOrProductName = select * from (select rownum no, p.* from (select * from product order by reg_date) p) p where % like ?
findById = select * from (select rownum no, p.* from (select * from product order by reg_date) p) p where id = ?
insertProduct = insert into product values (?, ?, ?, ?, ?, ?, ?, default, default)
updateProduct = update product set % = ? where id = ?
deleteProduct = delete from product where id = ?
findAllAboutProductIO = select * from product_io order by io_datetime
findByNO = select id from (select rownum no, p.* from (select * from product order by reg_date) p) p where no = ?
insertProductIO = insert into product_io values (seq_product_io_no.nextval, ?, ?, ?, default)
cancelProductIO = insert into product_io values (seq_product_io_no.nextval, ?, ?, ?, default)

 

SQL

--==============================================
-- product 계정
--==============================================
-- product 테이블 생성 (상품 상세테이블)
-- drop table product;
create table product (
    id varchar2(30),
    brand varchar2(50) not null,
    name varchar2(30) not null,
    price number(10) not null,
    monitor_size number,
    os varchar2(100),
    storage number,
    stock number default 0,
    reg_date date default sysdate,
    constraint pk_product_id primary key(id),
    constraint ck_product_stock check (stock >= 0)
);

-- product_io 테이블 생성 (상품입출고 테이블)
--drop table product_io;
create table product_io (
    no number,  -- sequence처리
    product_id varchar2(30),
    count number,
    status char(1),
    io_datetime timestamp default systimestamp,
    constraint pk_product_io_no primary key(no),
    constraint fk_product_io_product_id foreign key(product_id) references product(id) on delete cascade,
    constraint ck_product_io_count check (count >= 0),
    constraint ck_product_io_status check (status in ('I', 'O'))
);

-- sequence 생성
create sequence seq_product_io_no;

-- trigger 생성
create or replace trigger tri_product_io_stock
    before
    insert on product_io
    for each row
begin
    -- 입고 시
    if :new.status = 'I' then
        update product 
        set stock = stock + :new.count
        where id = :new.product_id;
    -- 출고시
    elsif :new.status = 'O' then
        update product 
        set stock = stock - :new.count
        where id = :new.product_id;
    end if;
end;
/

 


실행해보기

=============================
🎁 상 품 재 고 관 리 프 로 그 램 🎁
=============================
1. 전체 상품 조회
2. 상품 검색
3. 상품 등록
4. 상품 정보 변경
5. 상품 삭제
6. 상품 입/출고 메뉴
0. 프로그램 종료
-----------------------------
번호 선택 → 1
=================================================================================
 	                           🎁 상 품 조 회 결 과 🎁                         
=================================================================================
no   id                brand     name      price     spec           stock   
--------------------------------------------------------------------------------
1    X413EA-EB086      ASUS    바부복       609,000원  14인치/Window10/350GB   50
--------------------------------------------------------------------------------

=============================
🎁 상 품 재 고 관 리 프 로 그 램 🎁
=============================
1. 전체 상품 조회
2. 상품 검색
3. 상품 등록
4. 상품 정보 변경
5. 상품 삭제
6. 상품 입/출고 메뉴
0. 프로그램 종료
-----------------------------
번호 선택 → 2

----------------------------------------------------------------
                    🎁 상 품 검 색 메 뉴 🎁                         
----------------------------------------------------------------
1. 아이디 검색
2. 상품명 검색
0. 메인 메뉴로 돌아가기
----------------------------------------------------------------
번호 선택 → 1
> 상품의 ID를 입력하세요 → x
=================================================================================
 	                           🎁 상 품 조 회 결 과 🎁                         
=================================================================================
no   id                brand     name      price     spec           stock   
--------------------------------------------------------------------------------
1    X413EA-EB086      ASUS    바부복       609,000원  14인치/Window10/350GB   50
--------------------------------------------------------------------------------

----------------------------------------------------------------
                    🎁 상 품 검 색 메 뉴 🎁                         
----------------------------------------------------------------
1. 아이디 검색
2. 상품명 검색
0. 메인 메뉴로 돌아가기
----------------------------------------------------------------
번호 선택 → 2
> 상품의 상품명을 입력하세요 → 바부복
=================================================================================
 	                           🎁 상 품 조 회 결 과 🎁                         
=================================================================================
no   id                brand     name      price     spec           stock   
--------------------------------------------------------------------------------
1    X413EA-EB086      ASUS    바부복       609,000원  14인치/Window10/350GB   50
--------------------------------------------------------------------------------

----------------------------------------------------------------
                    🎁 상 품 검 색 메 뉴 🎁                         
----------------------------------------------------------------
1. 아이디 검색
2. 상품명 검색
0. 메인 메뉴로 돌아가기
----------------------------------------------------------------
번호 선택 → 0

=============================
🎁 상 품 재 고 관 리 프 로 그 램 🎁
=============================
1. 전체 상품 조회
2. 상품 검색
3. 상품 등록
4. 상품 정보 변경
5. 상품 삭제
6. 상품 입/출고 메뉴
0. 프로그램 종료
-----------------------------
번호 선택 → 3
> 상품의 ID를 입력하세요 → MVVK2KH/A
[MVVK2KH/A]는 등록 가능한 상품입니다 :)
> 상품의 브랜드를 입력하세요 → Apple
> 상품의 이름을 입력하세요 → 맥북프로
> 상품의 가격을 입력하세요(ex.1000000) → 3705690
> 상품의 모니터 크기를 입력하세요(ex.15) → 16
> 상품의 운영체제를 입력하세요 → macOS
> 상품의 용량을 입력하세요(ex.256) → 512
> 상품 등록 성공!

=============================
🎁 상 품 재 고 관 리 프 로 그 램 🎁
=============================
1. 전체 상품 조회
2. 상품 검색
3. 상품 등록
4. 상품 정보 변경
5. 상품 삭제
6. 상품 입/출고 메뉴
0. 프로그램 종료
-----------------------------
번호 선택 → 4
=================================================================================
 	                           🎁 상 품 조 회 결 과 🎁                         
=================================================================================
no   id                brand     name      price     spec           stock   
--------------------------------------------------------------------------------
1    X413EA-EB086      ASUS    바부복       609,000원  14인치/Window10/350GB   50
2    MVVK2KH/A         Apple   맥북프로      3,705,690원  16인치/macOS/512GB    0
--------------------------------------------------------------------------------
> 변경할 상품의 NO을 입력하세요 → 2

----------------------------------------------------------------
                    🎁 상 품 변 경 메 뉴 🎁                         
----------------------------------------------------------------
1. 상품명 변경
2. 가격 변경
3. 사양 변경
0. 메인 메뉴로 돌아가기
----------------------------------------------------------------
번호 선택 → 1
=================================================================================
 	                           🎁 상 품 조 회 결 과 🎁                         
=================================================================================
no   id                brand     name      price     spec           stock   
--------------------------------------------------------------------------------
2    MVVK2KH/A         Apple   맥북프로      3,705,690원  16인치/macOS/512GB    0
--------------------------------------------------------------------------------
> 변경하실 상품명을 입력하세요 → 맥북프로13
> 정보 변경 성공!
=================================================================================
 	                           🎁 상 품 조 회 결 과 🎁                         
=================================================================================
no   id                brand     name      price     spec           stock   
--------------------------------------------------------------------------------
2    MVVK2KH/A         Apple   맥북프로13    3,705,690원  16인치/macOS/512GB    0
--------------------------------------------------------------------------------

----------------------------------------------------------------
                    🎁 상 품 변 경 메 뉴 🎁                         
----------------------------------------------------------------
1. 상품명 변경
2. 가격 변경
3. 사양 변경
0. 메인 메뉴로 돌아가기
----------------------------------------------------------------
번호 선택 → 2
=================================================================================
 	                           🎁 상 품 조 회 결 과 🎁                         
=================================================================================
no   id                brand     name      price     spec           stock   
--------------------------------------------------------------------------------
2    MVVK2KH/A         Apple   맥북프로13    3,705,690원  16인치/macOS/512GB    0
--------------------------------------------------------------------------------
> 변경하실 가격을 입력하세요 → 50000000
> 정보 변경 성공!
=================================================================================
 	                           🎁 상 품 조 회 결 과 🎁                         
=================================================================================
no   id                brand     name      price     spec           stock   
--------------------------------------------------------------------------------
2    MVVK2KH/A         Apple   맥북프로13    50,000,000원  16인치/macOS/512GB    0
--------------------------------------------------------------------------------

----------------------------------------------------------------
                    🎁 상 품 변 경 메 뉴 🎁                         
----------------------------------------------------------------
1. 상품명 변경
2. 가격 변경
3. 사양 변경
0. 메인 메뉴로 돌아가기
----------------------------------------------------------------
번호 선택 → 0
=================================================================================
 	                           🎁 상 품 조 회 결 과 🎁                         
=================================================================================
no   id                brand     name      price     spec           stock   
--------------------------------------------------------------------------------
2    MVVK2KH/A         Apple   맥북프로13    50,000,000원  16인치/macOS/512GB    0
--------------------------------------------------------------------------------

=============================
🎁 상 품 재 고 관 리 프 로 그 램 🎁
=============================
1. 전체 상품 조회
2. 상품 검색
3. 상품 등록
4. 상품 정보 변경
5. 상품 삭제
6. 상품 입/출고 메뉴
0. 프로그램 종료
-----------------------------
번호 선택 → 6

----------------------------------------------------------------
                    🎁 상 품 입 출 고 메 뉴 🎁                         
----------------------------------------------------------------
1. 입출고 내역 조회
2. 상품 입고
3. 상품 출고
0. 메인 메뉴로 돌아가기
----------------------------------------------------------------
번호 선택 → 1
=================================================================================
 	                           🎁 상 품 조 회 결 과 🎁                         
=================================================================================
no   id                brand     name      price     spec           stock   
--------------------------------------------------------------------------------
1    X413EA-EB086      ASUS    바부복       609,000원  14인치/Window10/350GB   50
2    MVVK2KH/A         Apple   맥북프로13    50,000,000원  16인치/macOS/512GB    0
--------------------------------------------------------------------------------
================================================================
                    🎁 입 출 고 내 역 조 회 🎁                         
================================================================
no   productId           count     status    IODate    
----------------------------------------------------------------
21   X413EA-EB086        15        I         2022-05-09 13:15:18.824
41   X413EA-EB086        5         O         2022-05-09 13:22:37.953
121  X413EA-EB086        20        I         2022-05-09 15:04:26.339
122  X413EA-EB086        20        I         2022-05-09 15:04:26.379
128  X413EA-EB086        10        I         2022-05-09 15:12:13.201
130  X413EA-EB086        10        O         2022-05-09 15:12:25.317
----------------------------------------------------------------

----------------------------------------------------------------
                    🎁 상 품 입 출 고 메 뉴 🎁                         
----------------------------------------------------------------
1. 입출고 내역 조회
2. 상품 입고
3. 상품 출고
0. 메인 메뉴로 돌아가기
----------------------------------------------------------------
번호 선택 → 2
=================================================================================
 	                           🎁 상 품 조 회 결 과 🎁                         
=================================================================================
no   id                brand     name      price     spec           stock   
--------------------------------------------------------------------------------
1    X413EA-EB086      ASUS    바부복       609,000원  14인치/Window10/350GB   50
2    MVVK2KH/A         Apple   맥북프로13    50,000,000원  16인치/macOS/512GB    0
--------------------------------------------------------------------------------
> 입고할 상품의 NO를 입력해주세요 → 2
> 상품의 입고 개수를 입력해주세요(ex.10) → 10
> 상품 입고 성공!

----------------------------------------------------------------
                    🎁 상 품 입 출 고 메 뉴 🎁                         
----------------------------------------------------------------
1. 입출고 내역 조회
2. 상품 입고
3. 상품 출고
0. 메인 메뉴로 돌아가기
----------------------------------------------------------------
번호 선택 → 3
=================================================================================
 	                           🎁 상 품 조 회 결 과 🎁                         
=================================================================================
no   id                brand     name      price     spec           stock   
--------------------------------------------------------------------------------
1    X413EA-EB086      ASUS    바부복       609,000원  14인치/Window10/350GB   50
2    MVVK2KH/A         Apple   맥북프로13    50,000,000원  16인치/macOS/512GB   10
--------------------------------------------------------------------------------
> 출고할 상품의 NO를 입력해주세요 → 5
> 존재하지 않는 NO입니다. 다시 입력해주세요.
> 출고할 상품의 NO를 입력해주세요 → 2
> 상품의 출고 개수를 입력해주세요(ex.10) → 5
> 상품 출고 성공!

----------------------------------------------------------------
                    🎁 상 품 입 출 고 메 뉴 🎁                         
----------------------------------------------------------------
1. 입출고 내역 조회
2. 상품 입고
3. 상품 출고
0. 메인 메뉴로 돌아가기
----------------------------------------------------------------
번호 선택 → 1
=================================================================================
 	                           🎁 상 품 조 회 결 과 🎁                         
=================================================================================
no   id                brand     name      price     spec           stock   
--------------------------------------------------------------------------------
1    X413EA-EB086      ASUS    바부복       609,000원  14인치/Window10/350GB   50
2    MVVK2KH/A         Apple   맥북프로13    50,000,000원  16인치/macOS/512GB    5
--------------------------------------------------------------------------------
================================================================
                    🎁 입 출 고 내 역 조 회 🎁                         
================================================================
no   productId           count     status    IODate    
----------------------------------------------------------------
21   X413EA-EB086        15        I         2022-05-09 13:15:18.824
41   X413EA-EB086        5         O         2022-05-09 13:22:37.953
121  X413EA-EB086        20        I         2022-05-09 15:04:26.339
122  X413EA-EB086        20        I         2022-05-09 15:04:26.379
128  X413EA-EB086        10        I         2022-05-09 15:12:13.201
130  X413EA-EB086        10        O         2022-05-09 15:12:25.317
161  MVVK2KH/A           10        I         2022-05-10 14:15:25.177
162  MVVK2KH/A           5         O         2022-05-10 14:15:31.653
----------------------------------------------------------------

----------------------------------------------------------------
                    🎁 상 품 입 출 고 메 뉴 🎁                         
----------------------------------------------------------------
1. 입출고 내역 조회
2. 상품 입고
3. 상품 출고
0. 메인 메뉴로 돌아가기
----------------------------------------------------------------
번호 선택 → 0
=================================================================================
 	                           🎁 상 품 조 회 결 과 🎁                         
=================================================================================
no   id                brand     name      price     spec           stock   
--------------------------------------------------------------------------------
1    X413EA-EB086      ASUS    바부복       609,000원  14인치/Window10/350GB   50
2    MVVK2KH/A         Apple   맥북프로13    50,000,000원  16인치/macOS/512GB    5
--------------------------------------------------------------------------------

=============================
🎁 상 품 재 고 관 리 프 로 그 램 🎁
=============================
1. 전체 상품 조회
2. 상품 검색
3. 상품 등록
4. 상품 정보 변경
5. 상품 삭제
6. 상품 입/출고 메뉴
0. 프로그램 종료
-----------------------------
번호 선택 → 5
=================================================================================
 	                           🎁 상 품 조 회 결 과 🎁                         
=================================================================================
no   id                brand     name      price     spec           stock   
--------------------------------------------------------------------------------
1    X413EA-EB086      ASUS    바부복       609,000원  14인치/Window10/350GB   50
2    MVVK2KH/A         Apple   맥북프로13    50,000,000원  16인치/macOS/512GB    5
--------------------------------------------------------------------------------
> 상품의 ID를 입력하세요 → mvvk2kh/a
> 상품 삭제 성공!

=============================
🎁 상 품 재 고 관 리 프 로 그 램 🎁
=============================
1. 전체 상품 조회
2. 상품 검색
3. 상품 등록
4. 상품 정보 변경
5. 상품 삭제
6. 상품 입/출고 메뉴
0. 프로그램 종료
-----------------------------
번호 선택 → 6

----------------------------------------------------------------
                    🎁 상 품 입 출 고 메 뉴 🎁                         
----------------------------------------------------------------
1. 입출고 내역 조회
2. 상품 입고
3. 상품 출고
0. 메인 메뉴로 돌아가기
----------------------------------------------------------------
번호 선택 → 1
=================================================================================
 	                           🎁 상 품 조 회 결 과 🎁                         
=================================================================================
no   id                brand     name      price     spec           stock   
--------------------------------------------------------------------------------
1    X413EA-EB086      ASUS    바부복       609,000원  14인치/Window10/350GB   50
--------------------------------------------------------------------------------
================================================================
                    🎁 입 출 고 내 역 조 회 🎁                         
================================================================
no   productId           count     status    IODate    
----------------------------------------------------------------
21   X413EA-EB086        15        I         2022-05-09 13:15:18.824
41   X413EA-EB086        5         O         2022-05-09 13:22:37.953
121  X413EA-EB086        20        I         2022-05-09 15:04:26.339
122  X413EA-EB086        20        I         2022-05-09 15:04:26.379
128  X413EA-EB086        10        I         2022-05-09 15:12:13.201
130  X413EA-EB086        10        O         2022-05-09 15:12:25.317
----------------------------------------------------------------