재밌고 어려운 IT를 이해해보자~!

MVC with Oracle 1 본문

코리아IT핀테크과정

MVC with Oracle 1

언제나즐거운IT 2023. 12. 19. 17:00

오늘은 자바만 사용한것이 아닌 Oracle DBMS ( Database Management System ) 를 사용해서 

MVC 패턴으로 프로그램을 제작해보았다 !

DMBS는 다양한 종류가 존재한다. 우리는 그중 Oracle사용한다.

 

데이터 이관( Data Migration ) 이란 ? 

  Database와 Application을 새로운 Version으로 Upgrade하거나 새로운 System으로 바꿀 때 새로운 System에는 기존 Data가 존재해야만 한다.즉, 기존 System에서 사용하던 Data를 새로운 System에서 사용할 수 있도록 해야한다.그리고 기존전 System의 Data를 보존하면서 새로운 System에 맞게 변형시켜 사용할 수 있도록 저장하기 위함이다.

 

이관작업은 중요하다!

Oracle은 계정별로 적용되며  mysql은 스키마 (데이터베이스의 구조와 제약조건에 관해 전반적인 명세를 기술한 것 ) 를 통해 구성된다.


자바 C C++ 이런애들안 다완성해야 run이 되지만, Query Langauge는 script어이다. Line by Line 수행이 가능하다. 
왼쪽에 숫자가 붙는다는건 라인이 끝나지 않았다는 뜻이며, ; (세미콜론)을 붙여서 라인을 종료시킨다 .


쿼리는 소문자를 써돔 먹히지만 개발자라면 대문자로 작성해야 가독성이 좋아지고  자바와 혼합했을떄 구분이 쉬워진다.
디비버 SQLDEVELOPER 를 사용하면 더 쉽게 다룰 수 있지만 수업에서는 자바를 이용해서 Query를 다룬다.

 

DDL (Data Definition Language), DML (Data Manipulation Language) 위주로 다루며 공부한다.

 

이클립스랑 오라클을 연동해보자!

==================================================

sqlplus sys/oracle as sysdba                   <<< 접속방법
      =sysdba 최상위 관리자

입력:      CREATE USER 이름
   2 IDENTIFIED BY 비번
   3 ACCOUNT UNLOCK;

출력 :    User created. <<< 메시지가 나오면 성공 

위에 이름 / 번호 / 계정언락 과정을 명령을 3번 한 것이 아니라 세미클론이 한번 적용된 한줄의 명령임

입력 : GRANT CONNECT, RESOURCE TO PIPIN;

출력 : Grant succeeded.

쿼리는 대소문자를 구분하지는 않아서 소문자로 써도 괜찮지만, 자바내부에서 사용할 예정이기 때문에
가독성을 위해 대문자로 작성해줘야함 ★★

DB연결

이클립스 - window / other / data 검색 -> data Source Explorer ->  Database Connections 우클릭 / new 클릭
oracle 찾아서 선택 

오라클의 시스템과 이클립스 시스템을 연결하기 위해 드라이버가 필요함 

new driver definition 클릭
oracle 11버젼 

한 칸 옆 카테고리 JAR LIST 선택  / 14버젼 남아있으면 remove로 삭제 진행

resource에서 JAR6추가하고 , ok 누르고 넘김

General 옵션에서 Service Name : XE로 변경

HOST : localhost로 변경
port number 1521 확인
아이디 
비밀번호 입력
save password 체크

test Connection 클릭
success 뜨면서 Ping succeeded! 뜨면 성공 

==================================================


cmd는로는 계정을 만든 것 이고, 이클립스와 데이터베이스를 연결할때 필요한게 Driver이다. 
Database Connection은 오라클이랑 이클립스랑 연결은 한것이다.

 

또한 실행을 시킬때 SQLException Error 가 나올 수 있는데 이때는 

Java Project 우클릭 -> properties -> Java Build Path ->  Classpath에 Add External JARs... 를 클릭해서

기존에 사용하던 jar파일을 추가해주자.

 

SQL file

-- DDL 데이터가 들어갈 공간을 정의할때 사용하는 언어
--             == 테이블
-- DML 데이터를 조작하는 언어 ◀

-- CREATE
--  테이블을 생성할때 사용
--  "제약조건" : 해당 컬럼이 ~~해야한다라는 '강제'사항
CREATE TABLE PRODUCT(
	PID		INT				PRIMARY KEY,
	NAME	VARCHAR(15)		NOT NULL,
	PRICE	INT,
	CNT		INT				DEFAULT 10
);

-- DROP
--  테이블을 삭제할때 사용
DROP TABLE PRODUCT;



-- INSERT
--  데이터를 테이블에 추가할때 사용
INSERT INTO PRODUCT VALUES(1001,'콜라',1100,1);
INSERT INTO PRODUCT VALUES(1002,'사이다',1200,3);
INSERT INTO PRODUCT (PID,NAME,PRICE) VALUES(1003,'환타',1500);
INSERT INTO PRODUCT VALUES(1004,'환타포도',1500,0);
INSERT INTO PRODUCT VALUES((SELECT NVL(MAX(PID),1000) + 1 FROM PRODUCT),'샘플',0,0);
-- 서브쿼리
-- 오라클(DBMS)에서 서브쿼리를 통해 자동증가를 구현
-- NVL(값,초기값) : 값이 NULL이야? 그럼 초기값으로 해줘~~!


-- SELECT
--  테이블의 데이터를 출력할때 사용
SELECT * FROM PRODUCT;
SELECT PID,NAME FROM PRODUCT;
SELECT PID,NAME FROM PRODUCT WHERE PID>=1002;
SELECT PID,NAME FROM PRODUCT WHERE 3<=CNT AND CNT<=5;
SELECT PID,NAME FROM PRODUCT ORDER BY PID ASC;
SELECT PID,NAME FROM PRODUCT ORDER BY PID DESC;
SELECT PID,NAME FROM PRODUCT WHERE PID>=1002 ORDER BY PID DESC;
SELECT PID,NAME FROM PRODUCT WHERE NAME LIKE '%환타%';

-- UPDATE
--  테이블의 데이터를 변경할때 사용
SELECT PID,NAME,CNT FROM PRODUCT WHERE PID=1001;
UPDATE PRODUCT SET CNT=0 WHERE PID=1001;
UPDATE PRODUCT SET CNT=CNT-1 WHERE PID=1001;

-- DELETE
--  테이블의 데이터를 삭제할때 사용
DELETE FROM PRODUCT WHERE PID=1004;

 

사용한 Query 문으로는 

DDL => Creat, Drop

DML =>  Select, Insert, Update, Delete 

 

WHERE과 ORDER BY 를 사용해서 조건을 설정해줄 수 있으며 ASC : 오름차순 정렬 DESC : 내림차순 정렬이다.

 

JDBCUtil

package model;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;

// 다양한 DAO에서
//  연결(), 해제() 를 사용할 예정
//   => 별도의 Util 클래스로 '모듈화'
public class JDBCUtil {
	
	static final String driverName="oracle.jdbc.driver.OracleDriver";
	static final String url="jdbc:oracle:thin:@localhost:1521:xe";
	static final String user="teemo";
	static final String passwd="1234";
	
	public static Connection connect() {
		Connection conn=null;
		
		try {
			// 1. driver를 메모리에 로드 == 적재
			Class.forName(driverName);
			
			// 2. conn 객체를 확보
			conn=DriverManager.getConnection(url,user,passwd);
		} catch (ClassNotFoundException | SQLException e) {
			e.printStackTrace();
		}
		
		return conn;
	}
	
	public static void disconnect(PreparedStatement pstmt, Connection conn) {
		try {
			// 4. 연결 해제
			pstmt.close();
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
}

 

JDBC란?

JDBC는 Java에서 Database를 사용할 수 있게 해주는 API로 

JDBC : Java DataBase Connectivity의 약자이며 Database 종류와 상관없이 사용할 수 있다.

 

JDBC를 사용하기 위해선 JDBC를 사용하기 위해서는 JDBC 드라이버를 설치해야 한다.

여기서 드라이버는 드라이버란 운영 체제와 장치의 상호 통신을 허용하는 소프트웨어 구성 요소이며 컴퓨터와 연결된 특정장치와 통신하여 이를 제어하는 역할을 하는 프로그램이다.

JDBC Driver는 DB와 통신을 담당하는 자바 클래스이며, DB 종류에 맞는 드라이버를 사용하면 된다. 

(보통 .jar 파일)

JDBC 동작 순서

JDBC의 동작 순서는 아래 순서대로 작동한다.

  1. DB Driver를 Java 메모리 상으로 load : Class.forName(driver)
  2. Driver를 통해 Java와 DB를 연결(connection)한다.
    • 연결할 때, url, Id, password를 넘겨준다
    • url은 DB의 위치, Id는 DB의 계정(MySQL 기준 보통 root), password (사용자가 설정한 DB의 비밀번호)
    • con = DriverManager.getConnection(url, Id, password)
  3. 연결이 됐다면, statement 또는 preparedstatement로 쿼리문을 전송한다.
    • stmt = con.createStatement()
    • pstmt = con.prepareStatement()
  4. 쿼리 작성 String으로 선언하고, 변수에 입력
    • String sql = "SELECT * FROM book"
  5. 작성한 쿼리 전송
    • res = stmt.executeQuery(sql)
  6. 쿼리문이 SELECT ResultSet으로 받고, 그 외에는 int로 받는다. (반환 타입)
  7. 쿼리를 다 사용했다면, ResultSet부터 역순으로 리소스 close()를 진행한다.

VIEW

package view;

import java.util.ArrayList;
import java.util.Scanner;

import model.ProductDTO;

public class VIEW {
	private Scanner sc;
	public VIEW() {
		sc=new Scanner(System.in);
	}
	
	public void printMenu() {
		System.out.println("0. 종료");
		System.out.println("1. 추가");
		System.out.println("2. 목록");
		System.out.println("3. 번호로 검색");
		System.out.println("4. 구매");
		System.out.println("5. 삭제");
		System.out.println("6. 이름으로 검색");
	}
	public int inputAction() {
		System.out.print("번호입력 >> ");
		return sc.nextInt();
	}
	
	public void printDatas(ArrayList<ProductDTO> datas) {
		for(ProductDTO data:datas) {
			if(data.getCnt()<=0) {
				System.out.println(data.getName()+" 품절!");
				continue;
			}
			System.out.println(data);
		}
	}
	
	public int inputPid() {
		System.out.print("상품번호입력 >> ");
		return sc.nextInt();
	}
	public void printData(ProductDTO data) {
		if(data==null) {
			System.out.println("해당 상품은 존재하지않습니다...");
			return;
		}
		System.out.println(data);
	}
	public void printInfo(ProductDTO data) {
		if(data==null) {
			System.out.println("해당 상품이 존재하지않아 구매가 불가능합니다...");
		}
		else if(data.getCnt()<=0) {
			System.out.println(data.getName()+" 상품은 품절입니다!");
			System.out.println("재입고를 기다려주세용,,");
		}
	}
	
	public String inputName() {
		System.out.print("상품이름입력 >> ");
		return sc.next();
	}
	public int inputPrice() {
		System.out.print("상품가격입력 >> ");
		return sc.nextInt();
	}
	public int inputCnt() {
		System.out.print("상품재고입력 >> ");
		return sc.nextInt();
	}
	public void printTrue() {
		System.out.println("성공!");
	}
	public void printFalse() {
		System.out.println("실패...");
	}
}

productDTO

package model;

public class ProductDTO {
	private int pid;
	private String name;
	private int price;
	private int cnt;
	
	private String searchCondition;
	public String getSearchCondition() {
		return searchCondition;
	}
	public void setSearchCondition(String searchCondition) {
		this.searchCondition = searchCondition;
	}
	
	public int getPid() {
		return pid;
	}
	public void setPid(int pid) {
		this.pid = pid;
	}
	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 getCnt() {
		return cnt;
	}
	public void setCnt(int cnt) {
		this.cnt = cnt;
	}
	@Override
	public String toString() {
		return "ProductDTO [pid=" + pid + ", name=" + name + ", price=" + price + ", cnt=" + cnt + "]";
	}
}

productDAO

package model;

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

public class ProductDAO {

	private Connection conn; // DB와의 연결을 담당
	private PreparedStatement pstmt; // CRUD 수행을 담당

	private static final String SELECTALL="SELECT * FROM PRODUCT";
	private static final String SELECTALL_NAME="SELECT * FROM PRODUCT WHERE NAME LIKE '%'||?||'%'";
	private static final String SELECTONE="SELECT * FROM PRODUCT WHERE PID=?";

	private static final String INSERT="INSERT INTO PRODUCT VALUES((SELECT NVL(MAX(PID),1000) + 1 FROM PRODUCT),?,?,?)";
	private static final String UPDATE="UPDATE PRODUCT SET CNT=CNT-1 WHERE PID=?";
	private static final String DELETE="DELETE FROM PRODUCT WHERE PID=?";

	public ArrayList<ProductDTO> selectAll(ProductDTO pDTO){
		ArrayList<ProductDTO> datas=new ArrayList<ProductDTO>();

		conn=JDBCUtil.connect();
		try {
			// 3. pstmt 로 CRUD 수행
			if(pDTO.getSearchCondition().equals("전체")) {
				pstmt=conn.prepareStatement(SELECTALL);
			}
			else { // 이름
				pstmt=conn.prepareStatement(SELECTALL_NAME);
				pstmt.setString(1, pDTO.getName());
			}
			ResultSet rs=pstmt.executeQuery();

			while(rs.next()) {
				ProductDTO data=new ProductDTO();
				data.setPid(rs.getInt("PID"));
				data.setName(rs.getString("NAME"));
				data.setPrice(rs.getInt("PRICE"));
				data.setCnt(rs.getInt("CNT"));
				datas.add(data);
			}

			rs.close();
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			JDBCUtil.disconnect(pstmt, conn);
		}

		return datas;
	}
	public ProductDTO selectOne(ProductDTO pDTO){
		ProductDTO data=null;

		conn=JDBCUtil.connect();
		try {
			pstmt=conn.prepareStatement(SELECTONE);
			pstmt.setInt(1, pDTO.getPid());
			ResultSet rs=pstmt.executeQuery();

			if(rs.next()) {
				data=new ProductDTO();
				data.setPid(rs.getInt("PID"));
				data.setName(rs.getString("NAME"));
				data.setPrice(rs.getInt("PRICE"));
				data.setCnt(rs.getInt("CNT"));
			}

			rs.close();
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			JDBCUtil.disconnect(pstmt, conn);
		}		

		return data;
	}
	public boolean insert(ProductDTO pDTO) {
		conn=JDBCUtil.connect();
		try {
			pstmt=conn.prepareStatement(INSERT);
			pstmt.setString(1, pDTO.getName());
			pstmt.setInt(2, pDTO.getPrice());
			pstmt.setInt(3, pDTO.getCnt());
			int result=pstmt.executeUpdate();
			if(result<=0) {
				return false;
			}
		} catch (SQLException e) {
			e.printStackTrace();
			return false;
		} finally {
			JDBCUtil.disconnect(pstmt, conn);
		}		
		return true;
	}
	public boolean update(ProductDTO pDTO) {
		conn=JDBCUtil.connect();
		try {
			pstmt=conn.prepareStatement(UPDATE);
			pstmt.setInt(1, pDTO.getPid());
			int result=pstmt.executeUpdate();
			if(result<=0) {
				return false;
			}
		} catch (SQLException e) {
			e.printStackTrace();
			return false;
		} finally {
			JDBCUtil.disconnect(pstmt, conn);
		}		
		return true;	
	}
	public boolean delete(ProductDTO pDTO) {
		conn=JDBCUtil.connect();
		try {
			pstmt=conn.prepareStatement(DELETE);
			pstmt.setInt(1, pDTO.getPid());
			int result=pstmt.executeUpdate();
			if(result<=0) {
				return false;
			}
		} catch (SQLException e) {
			e.printStackTrace();
			return false;
		} finally {
			JDBCUtil.disconnect(pstmt, conn);
		}		
		return true;
	}

}

CTRL

package ctrl;

import model.ProductDAO;
import model.ProductDTO;
import view.VIEW;

public class CTRL {

	private ProductDAO pDAO;
	private VIEW view;

	public CTRL() {
		pDAO=new ProductDAO();
		view=new VIEW();
	}

	public void start() {
		while(true) {
			view.printMenu();
			int action=view.inputAction();
			if(action==0) {
				break;
			}
			else if(action==1) {
				String name=view.inputName();
				int price=view.inputPrice();
				int cnt=view.inputCnt();
				ProductDTO pDTO=new ProductDTO();
				pDTO.setName(name);
				pDTO.setPrice(price);
				pDTO.setCnt(cnt);
				boolean flag=pDAO.insert(pDTO);
				if(!flag) {
					view.printFalse();
					continue;
				}
				view.printTrue();
			}
			else if(action==2) {
				ProductDTO pDTO=new ProductDTO();
				pDTO.setSearchCondition("전체");
				view.printDatas(pDAO.selectAll(pDTO));
			}
			else if(action==3) {
				int pid=view.inputPid();
				ProductDTO pDTO=new ProductDTO();
				pDTO.setPid(pid);
				view.printData(pDAO.selectOne(pDTO));
			}
			else if(action==4) {
				int pid=view.inputPid();
				ProductDTO pDTO=new ProductDTO();
				pDTO.setPid(pid);
				pDTO=pDAO.selectOne(pDTO);
				if(pDTO==null || pDTO.getCnt()<=0) {
					view.printInfo(pDTO);
					continue;
				}
				
				boolean flag=pDAO.update(pDTO);
				if(!flag) {
					view.printFalse();
					continue;
				}
				view.printTrue();
			}
			else if(action==5) {
				int pid=view.inputPid();
				ProductDTO pDTO=new ProductDTO();
				pDTO.setPid(pid);
				boolean flag=pDAO.delete(pDTO);
				if(!flag) {
					view.printFalse();
					continue;
				}
				view.printTrue();
			}
			else if(action==6) {
				String name=view.inputName();
				ProductDTO pDTO=new ProductDTO();
				pDTO.setName(name);
				pDTO.setSearchCondition("이름");
				view.printDatas(pDAO.selectAll(pDTO));
			}
		}
	}

}

 

'코리아IT핀테크과정' 카테고리의 다른 글

웹서버 프로그래밍 시험 오답노트  (0) 2023.12.21
MVC with Oracle 2  (0) 2023.12.20
MVC Pattern Practice 4  (0) 2023.12.18
MVC Pattern Practice 3  (0) 2023.12.17
MVC Pattern Practice 2  (0) 2023.12.14
Comments