CafeMenu 만들기

yookyungmin·2022년 9월 13일
0

DAO

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.dbcp2.BasicDataSource;

//데이터 접근 오브젝트 DAO
public class CafeMenuDAO {

	

	//	private Connection getConnection() throws Exception{  // 똑같은 코드 반복 묶기
	//		String url = "jdbc:oracle:thin:@localhost:1521:xe";
	//		String id = "kh";
	//		String pw = "kh";
	//
	//		Connection con = DriverManager.getConnection(url,id,pw);
	//		return con;
	//	} //DBCP로 인해 삭제

//		왜 Singleton을 써야 하는가 
//		
//		기존처럼 Main(뷰)에서 CafeMenuDAO dao = new CafeMenuDAO(); 를 다수의 사용자가 발생하면 접속자 한명한명마다 DAO를 하나씩 만들어서 쓰는데( 따로따로 코드를 실행)
//		CafeMenuDAO dao = new CafeMenuDAO(); 하면 내부의 	private BasicDataSource bds = new BasicDataSource(); 도 계속 생성이 되면
//		 BasicDataSource의 커넥션도 this.bds.setInitialSize(30); 30개 60개 ~  계속 생성되기 떄문에 생성자로 빼두고, 
//		싱글톤 패턴 사용으로 한개의 DAO만을 가지고 여러명이 사용하게끔 


	//왜 싱글톤패턴에 Static을 사용하는가?
	// static 은 new , 객체 생성없이 사용 가능.  // 싱글톤패턴을 사용하려는데 어떻게 new 없이 접근을 할것인가 ? 그래서 public static CafeMenuDAO getInstance() static으로 만들어서
	//객체생성없이 CafeMenuDAO dao = CafeMenuDAO.getInstance(); 접근을 하고 if 과정을 통해 new CafeMenuDAO()를 사용하기 위함.



	//	Singleton Pattern
	//	특정 클래스들은 new를 자유롭게 사용해선 안되고 단하나의 인스턴스로만 사용하게끔 제한해야 하는데, 
	//	이떄 사용 되는 디자인 패턴
	//	들어오는 접속자마다 DAO를 생성하는게 아니라 하나를 만들어놓고 하나가지고
	//여러명이 쓰게끔 해줘야 함

	
	
	private static CafeMenuDAO instance = null;

	public synchronized static CafeMenuDAO getInstance() { //싱글톤패턴
		if(instance == null) { // null과 같으면 true
			instance = new CafeMenuDAO();  //CafeMenuDAO의 주소가 instance에 들어감  , 
		}
		// 두번쨰 사용자부터는 instance의 값이 null값이 아닌 첫번쨰 사용자의해 이미 new CafeMenuDAO 되어 있기에 false가 되기때문에
		//바로 instance 값을 가지고 return  됨
		return instance;  //instance의 값을 가지고 메서드 콜한쪽으로 반환
	}
	//synchronized 메서드 작업이 끝날때까지 기다려줘야 함 다음 쓰레드로부터 안전한 쓰레드 세이프, 동시에 여러명이 사용하면 안되는 메서드에 사용,
	// 쓰레드 세이프로 인해 안전하지만 비용이라는 문제점이 생긴다.
	//싱글톤패턴도 DAO의 종류가 많아지면 싱글톤패턴도 무효화 될수 있다< 코드 상에 DBCP 를 만들지 않고 플랫폼에 DBCP 요청



	//DBCP : DATABASE Connection Pool, 데이터베이스에서 사용되는 커넥션 객체들의 울타리
	//dbcp 외장 라이브러리 인스턴스
	private BasicDataSource bds = new BasicDataSource(); // 바깥으로 new를 뺴두어야 커넥션 에러가 안남
	private CafeMenuDAO() { //생성자
		this.bds.setUrl("jdbc:oracle:thin:@localhost:1521:xe");
		this.bds.setUsername("kh");
		this.bds.setPassword("kh");
		this.bds.setDriverClassName("oracle.jdbc.driver.OracleDriver");
		this.bds.setInitialSize(30); //30개 Connection / 기본8?
	}

	private Connection getConnection() throws Exception{ 
		return bds.getConnection();
		//	bds.getConnection(); //DirverManager.getConnection과 유사
		//Connection 을 울타리에 미리 만들어놓고 대여&반환 시스템
	}



	public int insert(CafeMenuDTO dto) throws Exception{ 
		//Resultset SQL쿼리 떄문에 못뺴고, 커넥션처럼 뺸다 하더라도 리턴값을 하나밖에 못하기떄문에
		//throws Exception은 메서드에 넣어서 예외발생시 콜러(메서드 콜한 메인)한테 넘어간다 
		//메인메서드에선 throws Exception 하면 안됨 최후보루

		//중간에서 오류가 생겨 튕겼을때 close를 해주기 위해 try() {}  사용
		String sql = 
				"insert into cafe_menu values(cafe_menu_seq.nextval,?,?,?)";            

		try(Connection con = this.getConnection();
				PreparedStatement pstat = con.prepareStatement(sql);
				){

			pstat.setString(1, dto.getPname());
			pstat.setInt(2, dto.getPprice());
			pstat.setString(3, dto.getIced());
			int result = pstat.executeUpdate();

			con.commit();
			return result; 
			//close는 try() 에서 처리
		}        

		// 모델에선 예외처리 하지말고 뷰로
	}

	public int Delete(int delPID) throws Exception{
		String sql = "delete from cafe_menu where pid = ?";

		try(Connection con = this.getConnection();
				PreparedStatement pstat = con.prepareStatement(sql);){
			pstat.setInt(1, delPID);
			int result = pstat.executeUpdate();

			con.commit();	        
			return result;

		}


	}

	public boolean isPidExist(int pid) throws Exception{
		// 시퀸스 값을 하나 받아서 그값이 존재하는지 안하는지 
		//삭제시 존재여부 파악메서드 중요
		String sql = "select * from cafe_menu where pid = ?";

		try(Connection con = this.getConnection();
				PreparedStatement pstat = con.prepareStatement(sql);){
			pstat.setInt(1, pid);
			ResultSet rs = pstat.executeQuery();
			boolean result = rs.next();
			return result;	
		}


	}

	public int update(CafeMenuDTO dto) throws Exception {
		String sql = "update cafe_menu set  pname=?, pprice=?,iced=? where pid=?";

		try(Connection con = this.getConnection();
				PreparedStatement pstat = con.prepareStatement(sql);){
			pstat.setString(1, dto.getPname());
			pstat.setInt(2, dto.getPprice());
			pstat.setString(3, dto.getIced());
			pstat.setInt(4, dto.getPid());            
			int result = pstat.executeUpdate();

			con.commit();
			return result;
		}


	}

	public List<CafeMenuDTO> selectAll() throws Exception{  //출력문
		//Resultset 은 db 데이터 행 들을 화살표로 가르키고 있다
		//con, pstat, rs close 필요
		//ResultSet은 Close(를 하면 화살표가 끊김)전까지만 사용 가능
		//

		String sql = "select * from cafe_menu order by 1";
		try(			Connection con = getConnection();
				PreparedStatement pstat = con.prepareStatement(sql);
				ResultSet rs = pstat.executeQuery();){

			List<CafeMenuDTO>  result = new ArrayList(); //while문안으로넣으면 돌때마다 초기화
			//ResultSet을 바로 리턴할수 없기 떄문에 ResultSet을 ArrayList에 저장을 하고나서  close하고 ArrayList을 리턴
			//object 타입이라 다양한 타입 저장가능하지만 사용할때 다운캐스팅을 해야하기 떄문에
			//사용하기 어렵다 그래서 CafeMenuDTO 제네릭스 사용
			while(rs.next()) {
				int pid = rs.getInt("pid");
				String pname = rs.getString("pname");
				int pprice = rs.getInt("pprice");
				String iced = rs.getString("iced");
				CafeMenuDTO dto = new CafeMenuDTO(pid, pname, pprice, iced); //dto 에 담기
				result.add(dto);
			} //while문이 끝나는순간 ArrayList dto안에는 테이블 모든 내용이 담김
			return result;   //반환타입 ArrayList<CafeMenuDTO>
		}

	}
	public List<CafeMenuDTO> selectbyAll(int ppid) throws Exception{  //출력문

		String sql = "select * from cafe_menu where pid=? order by 1";
		try(			Connection con = getConnection();
				PreparedStatement pstat = con.prepareStatement(sql);
				){

			pstat.setInt(1, ppid);
			//select 문 시 ? 있을때 try() {} 이중으로 사용
			try(ResultSet rs = pstat.executeQuery();){

				List<CafeMenuDTO>  result = new ArrayList(); 

				while(rs.next()) {
					int pid = rs.getInt("pid");
					String pname = rs.getString("pname");
					int pprice = rs.getInt("pprice");
					String iced = rs.getString("iced");
					CafeMenuDTO dto = new CafeMenuDTO(pid, pname, pprice, iced); //dto 에 담기
					result.add(dto);
				} //while문이 끝나는순간 ArrayList dto안에는 테이블 모든 내용이 담김
				return result;   //반환타입 ArrayList<CafeMenuDTO>
			}

		}
	}
}

DTO



//VO Value object 값을 의미하는 객체
//DTO Data Transfer Object(값을 저장하고 전달하는 목적으로 사용되는 객체)
//강사님 DTO
public class CafeMenuDTO { 
	private int pid;
	private String pname;
	private int pprice;
	private String iced;
	
	
	
	
	
	public CafeMenuDTO(int pid, String pname, int pprice, String iced) {
		super();
		this.pid = pid;
		this.pname = pname;
		this.pprice = pprice;
		this.iced = iced;
	}
	public int getPid() {
		return pid;
	}
	public void setPid(int pid) {
		this.pid = pid;
	}
	public String getPname() {
		return pname;
	}
	public void setPname(String pname) {
		this.pname = pname;
	}
	public int getPprice() {
		return pprice;
	}
	public void setPprice(int pprice) {
		this.pprice = pprice;
	}
	public String getIced() {
		return iced;
	}
	public void setIced(String iced) {
		this.iced = iced;
	}
	

}

MAIN

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

import javax.annotation.processing.AbstractProcessor;

public class Exam05_CRUD2 {
	//PRPAREDSTATEMENT 사용
	//뷰(메인) 모델(CafeMenuDao) 나누기
	public static void main(String[] args)  {

//		try {
//			Class.forName("oracle.jdbc.driver.OracleDriver");
//		}catch (Exception e) {
//			e.printStackTrace();
//			System.exit(0); //DBMS연결 실패하면 시스템 종료
//		}
		Scanner sc = new Scanner(System.in);

		CafeMenuDAO dao = CafeMenuDAO.getInstance(); //static 메서드라서 객체생성없이 getInstance 호출
		//접속시마다 dao를 만드는게 아니라 하나의 Dao만 가지고 여러명이 사용

		while(true) {
			System.out.println("<< 카페 메뉴 관리 프로그램 >>");
			System.out.println("1. 신규 메뉴 등록");
			System.out.println("2. 메뉴 목록 출력");
			System.out.println("3. 메뉴 정보 삭제 (상품코드로 삭제)");
			System.out.println("4. 메뉴 정보 수정 (상품코드로 변경)");
			System.out.println("0. 프로그램 종료");
			System.out.print(">> ");
			int menu = Integer.parseInt(sc.nextLine());

			if(menu == 1) {
				System.out.print("메뉴 이름 : ");
				String pname = sc.nextLine();

				System.out.print("메뉴 가격 : ");
				int pprice = Integer.parseInt(sc.nextLine());

				System.out.print("아이스 가능 (Y,N) ? ");
				String iced = sc.nextLine();

				try {
					int result = dao.insert(new CafeMenuDTO(0, pname, pprice, iced)); //시퀸스값0 넣어도 ㄱㅊ
					if(result > 0) {
						System.out.println("입력 완료");
					}
				} catch (Exception e) {

					e.printStackTrace(); //반드시 남겨둠 에러의 원인을 보여줌
					System.out.println("같은 오류가 반복되면 관리자에게 문의하세요.");
				}

			}else if(menu == 2) {
				
				try {
				List<CafeMenuDTO> result = dao.selectAll(); //ArrayList가 List의 자손이기때문에 사용가능
				for(CafeMenuDTO dto :result) {
					System.out.println(dto.getPid()+"\t"+dto.getPname()+"\t"+dto.getPprice()+"\t"+dto.getIced());
				}
				}catch (Exception e) {
					e.printStackTrace();
				}
			}else if(menu == 3) {
				System.out.print("삭제할 상품 코드 : ");
				int delPID = Integer.parseInt(sc.nextLine());

				try {
					int result = dao.Delete(delPID);
					if(result > 0) {
						System.out.println("삭제 완료");
					}
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
					System.out.println("같은 오류가 반복되면 관리자에게 문의하세요.");
				}

			}else if(menu == 4) {

				System.out.print("변경할 메뉴의 상품 코드 : ");
				int updPID = Integer.parseInt(sc.nextLine());


				try {

					if(dao.isPidExist(updPID)) {

						System.out.print("메뉴 이름 : ");
						String pname = sc.nextLine();

						System.out.print("메뉴 가격 : ");
						int pprice = Integer.parseInt(sc.nextLine());

						System.out.print("아이스 가능 (Y,N) ? ");
						String iced = sc.nextLine();
						int result = dao.update(new CafeMenuDTO(updPID, pname, pprice, iced));
						//고유값을 시퀸스로 써서 굳이 PID를 변경할 필요가 없다

						if(result > 0) {
							System.out.println("변경 완료");
						}
					}else {
						System.out.println("수정할 대상 메뉴가 존재하지 않습니다");
					}
				}
				catch (Exception e) {
					e.printStackTrace();
					System.out.println("문제가 발생했습니다. 관리자에게 문의하세요.");
				}

			}else if(menu == 0) {
				System.out.println("프로그램을 종료합니다.");
				System.exit(0);
			}else {
				System.out.println("메뉴를 다시 확인해주세요.");
			}
		}

	}
}

0개의 댓글