8 minute read

24일차

JDBC (JAVA DataBase Connectivity)

자바 프로그램을 통해서 DBMS 를 사용하는 문법

  • 자바를 이용해서 Query를 날린다.

Oracle 은 Network 프로그램

JAVA는 Oracle 에서 사용하는 프로토콜을 이미 알고있는 라이브러리가 있다!

Oracle 라이브러리는 외장라이브러리다~~

Oracle 설치시 이미 라이브러리 설치됨.

Setup

경로

C:\oraclexe\app\oracle\product\11.2.0\server\jdbc\lib

외장 라이브러리를 Import 해준다.

ojdbc 라이브러리 등록

DB 관련 프로그램 동작시 등록과정이 필요함

Class.forName("oracle.jdbc.driver.OracleDriver");

Class.forName → new 를 사용하지 않고 instance 를 만들어내는 Reflection 기법

Class.forName()은 어떻게 동작할까?

DBMS 에 접속하기

Untitled

		String dbURL = "jdbc:oracle:thin:@localhost:1521:xe";
		
		//resource의 로케이션
		String dbID = "kh";
		String dbPW = "kh";
		Connection con = DriverManager.getConnection(dbURL + dbID + dbPW);
		// Driver는 Interface 클래스 이기에 인스턴스 생성후 반환받아야함.

jdbc:oracle:thin:

  • 우리는 오라클을 사용하기 때문에 default 값

@loaclhost:1521:xe

  • IP 주소와 (localhost = 개인 PC 주소)
  • Port 번호
  • SID : 데이터베이스 이름 XE 사용시 XE 고정

Untitled

select 문을 쓸때는 Resultset 을 리턴하는 executeQuery 사용

Query 를 전달할 인스턴스 생성

Statement stat = con.createStatement();
// statement 생성
		
String sql = "Query문 작성";
		
int result = stat.executeUpdate(sql);
// excuteUpdate 리턴값이 int이다.

Statement 객체란?

Untitled

  • DB 와 연결되는 connection 객체와의 의사소통을 위해서 DB에게 명령을 내릴 때 그 객체를 쏴주는 역할을 하는 Interface
  • 보안성에 문제가 있어 잘 사용되지 않음.
  • ' or 1=1 -- SQL INJECTION (보안성이 취약하다)

PreparedStatement

Statement 에 있어서 보안 취약점 (SQL Injection) 및 편의성을 보완함.

string sql = "inster into cafe_menu values (cafe_menu_seq.nextval, ?, ?, ?")"

preparedStatement pstat = con.prepareStatement(sql);

pstat.setString(1, pname);
pstat.setInt(2, pprice);
pstat.setString(3. iced);

int result = pstat.excuteUpdate();

Query 실행 결과 확인 및 마무리 작업

if(result > 0) {
			System.out.println("입력 성공");
		}else {
			System.out.println("입력 실패");
		}

// 5. 마무리 작업
// commit 후 종료 해준다.
con.commit();
con.close();

순서요약

라이브러리 등록 > 연결 > 쿼리 작성후 전달할 인스턴스 생성 > 결과확인

Query 실습

Row Delete

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;

public class Exam_01_1 {
	public static void main(String[] args) throws Exception{
		
		Class.forName("oracle.jdbc.driver.OracleDriver");
		
		String dbURL = "jdbc:oracle:thin:@localhost:1521:xe";
		String dbID = "kh";
		String dbPW = "kh";
		Connection con = DriverManager.getConnection(dbURL, dbID, dbPW);
		
		Statement stat = con.createStatement();
		String sql = "delete from cafe_menu where pname = 'Americano' ";
		int result = stat.executeUpdate(sql);
		
		if (result > 0) {
			System.out.println("삭제 완료");
		} else {
			System.out.println("삭제 실패");
		}

		con.commit();
		con.close();
		
	}

}

Update

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;

public class Exam_02 {
	public static void main(String[] args) throws Exception{
		// Americano 가격을 2500원으로 변경하는 프로그램 작성
		
		Class.forName("oracle.jdbc.driver.OracleDriver");
		
		String dbURL = "jdbc:oracle:thin:@localhost:1521:xe";
		String dbID = "kh";
		String dbPW = "kh";

		Connection con = DriverManager.getConnection(dbURL,dbID,dbPW);

		Statement stat = con.createStatement();
		String sql = "update cafe_menu set pprice = 2500 where pname = 'Americano'";
		int result = stat.executeUpdate(sql);
		
		if(result > 0) {
			System.out.println("수정 성공");
		}else {
			System.out.println("수정 실패");
		}

		con.commit();
		con.close();
		
		
	}

}

Select 쿼리 쏴보기

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

public class Exam_04_Select {
	public static void main(String[] args) throws Exception{
		Class.forName("oracle.jdbc.driver.OracleDriver");
		

		String dbURL = "jdbc:oracle:thin:@localhost:1521:xe";
		String dbID = "kh";
		String dbPW = "kh";
		Connection con = DriverManager.getConnection(dbURL,dbID,dbPW);

		Statement stat = con.createStatement();
		String sql = "Select * from cafe_menu order by 1";
		
		// excuteQuery 는 resultSet type을 return 합니다.
		ResultSet rs = stat.executeQuery(sql);
		// 지정값은 HeaderLine
		
		rs.next(); 
		// 주소를 한 횡 내려줌 HeaderLine to data
		// 데이터의 존재 유무에 따라서 boolean 값을 반환
		
		int pid = rs.getInt("pid");
		// rs가 가리키고있는 행의 PID 컬럼값을 INT 로 꺼내서 저장
		String pname = rs.getString("pname");
		int pprice = rs.getInt("pprice");
		
		System.out.println(pid + " : "+ pname + " : " + pprice);
		
		// 두 번째 횡 출력
		rs.next(); 
		pid = rs.getInt("pid");
		pname = rs.getString("pname");
		pprice = rs.getInt("pprice");
		
		System.out.println(pid + " : "+ pname + " : " + pprice);
		
		// 세 번째 횡 출력

		rs.next(); 
		pid = rs.getInt("pid");
		pname = rs.getString("pname");
		pprice = rs.getInt("pprice");
		System.out.println(pid + " : "+ pname + " : " + pprice);
		
		con.close();
		
	}

}

ResultSet

  • Select 쿼리의 결과를 담고있는 객체가 아님
  • 쿼리 결과 테이블(데이터)의 주소를 담고있는 객체.
  • 데이터를 꺼내올 때는 한 행 씩 꺼내와야 하는 것이 규칙.

Select 문 반복문으로 바꿔쓰기

while(rs.next()) { // 반복과 조건을 동시에!
											 // rs.next() 가 트루인 동안
			int pid = rs.getInt("pid");
			String pname = rs.getString("pname");
			int pprice = rs.getInt("pprice");

			System.out.println(pid + " : "+ pname + " : " + pprice);
}

CRUD Program (Use PreparedStatement)

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

public class Exam_05_CRUD {

	public static int getValidnum() { 
		// exception code
		Scanner sc = new Scanner(System.in);

		while (true) {
			try {
				int num = Integer.parseInt(sc.nextLine());
				return num;

			} catch (NumberFormatException e) {
				System.out.println("숫자를 입력해주세요.");
			}
		}

	}

	public static void main(String[] args) throws Exception{
		
		Scanner sc = new Scanner(System.in);
		
		
		Class.forName("oracle.jdbc.driver.OracleDriver");
		
		
		String dbURL = "jdbc:oracle:thin:@localhost:1521:xe";
		String dbID = "kh";
		String dbPW = "kh";
		Connection con;
		
		while(true){ // main interface
			
			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 = getValidnum();

			if (menu == 1) { // insert
				System.out.print("메뉴 이름 : ");
				String pname = sc.nextLine();
				
				System.out.print("메뉴 가격 : ");
				int pprice = getValidnum();
				
				System.out.print("아이스 가능 (Y, N) : ");
				String iced = sc.nextLine();
				
				con = DriverManager.getConnection(dbURL,dbID,dbPW);
				String sql = "insert into cafe_menu values(cafe_menu_seq.nextval,?,?,?)";
				
				PreparedStatement pstat = con.prepareStatement(sql);
				pstat.setString(1, pname);
				pstat.setInt(2,  pprice);
				pstat.setString(3, iced);
				
				int result = pstat.executeUpdate();
				
				if(result > 0) {
					System.out.println("입력 성공");
				}
				
				con.commit();
				con.close();
				
				

			} else if (menu == 2) { // select
				con = DriverManager.getConnection(dbURL,dbID,dbPW);

				String sql = "Select * from cafe_menu order by 1";
				PreparedStatement pstat = con.prepareStatement(sql);
				ResultSet rs = pstat.executeQuery();
				
				System.out.println("PID : PNAME : PPRICE : ICED");
				while(rs.next()) {
					int pid = rs.getInt("pid");
					String pname = rs.getString("pname");
					int pprice = rs.getInt("pprice");
					String iced = rs.getString("iced");

					System.out.println(pid + " : "+ pname + " : " + pprice + " : " + iced);
				}
				con.close();
				
			} else if (menu == 3) { // delete
				
				con = DriverManager.getConnection(dbURL, dbID, dbPW);
				
				System.out.print("삭제 할 메뉴의 상품코드(PID)을 입력해주세요 : ");
				String pid = sc.nextLine();
				
				String sql = "delete from cafe_menu where pid = ?";
				PreparedStatement pstat = con.prepareStatement(sql);
				pstat.setString(1, pid);
				
				int result = pstat.executeUpdate();
				
				if (result > 0) {
					System.out.println("삭제 완료");
				} else {
					System.out.println("삭제 실패");
				}
				con.commit();
				con.close();
			}
			
			else if (menu == 4) { //update
				
				con = DriverManager.getConnection(dbURL,dbID,dbPW);

				
				System.out.print("수정 할 메뉴의 상품코드(PID)을 입력해주세요 : ");
				String pid = sc.nextLine();
				System.out.print("수정 할 메뉴의 상품명을 입력하십시오 : ");
				String pname = sc.nextLine();
				System.out.print("수정 할 메뉴의 가격을 입력하십시오 : ");
				int pprice = getValidnum();
				System.out.print("얼음 추가 가능 유무 (Y, N): ");
				String iced = sc.nextLine();
				String sql = "update cafe_menu set pname = ?, pprice = ?, iced = ? where pid = ? ";
				PreparedStatement pstat = con.prepareStatement(sql);
				
				pstat.setString(1, pname);
				pstat.setInt(2, pprice);
				pstat.setString(3, iced);
				pstat.setString(4, pid);
				
				
				int result = pstat.executeUpdate();
				
				
				if(result > 0) {
					System.out.println("갱신 완료");
				}else {
					System.out.println("갱신 실패");
				}

				con.commit();
				con.close();
				
			}
			
			else if (menu == 0) {
				System.out.println("프로그램을 종료합니다.");
				System.exit(0);
			} else {
				System.out.println("잘못된 입력입니다.");
			}
			
		}

	}

}

MVC 적용하여 코드를 모듈화 하기

convention

data를 access 하는 클래스 → DAO (Data Access Object)

Main

import java.util.Scanner;

public class Exam_05_CRUD {

	public static int getValidnum() { 
		// exception code
		Scanner sc = new Scanner(System.in);

		while (true) {
			try {
				int num = Integer.parseInt(sc.nextLine());
				return num;

			} catch (NumberFormatException e) {
				System.out.println("숫자를 입력해주세요.");
			}
		}

	}

	public static void main(String[] args) {
		
		Scanner sc = new Scanner(System.in);
		
		
		try {
			Class.forName("oracle.jdbc.driver.OracleDriver");
		} catch (ClassNotFoundException e1) {
			e1.printStackTrace();
			System.out.println("에러가 발생했습니다.");
		}
		
		CafemenuDAO dao = new CafemenuDAO();
		
		
		
		while(true){ // main interface
			
			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 = getValidnum();

			if (menu == 1) { // insert
				System.out.print("메뉴 이름 : ");
				String pname = sc.nextLine();
				
				System.out.print("메뉴 가격 : ");
				int pprice = getValidnum();
				
				System.out.print("아이스 가능 (Y, N) : ");
				String iced = sc.nextLine();
				
				
				try { // 전가된 예외를 처리한다.
					int result = dao.insert(pname, pprice, iced);
					if (result > 0) {
						System.out.println("입력 완료.");
					}
				} catch (Exception e) {
					e.printStackTrace(); // 에러의 원인을 보여준다.
					System.out.println("같은 오류가 반복되면 관리자에게 문의하세요");
				}
				

			} else if (menu == 2) { // select
//				con = DriverManager.getConnection(dbURL,dbID,dbPW);
//
//				String sql = "Select * from cafe_menu order by 1";
//				PreparedStatement pstat = con.prepareStatement(sql);
//				ResultSet rs = pstat.executeQuery();
//				
//				System.out.println("PID : PNAME : PPRICE : ICED");
//				while(rs.next()) {
//					int pid = rs.getInt("pid");
//					String pname = rs.getString("pname");
//					int pprice = rs.getInt("pprice");
//					String iced = rs.getString("iced");
//
//					System.out.println(pid + " : "+ pname + " : " + pprice + " : " + iced);
//				}
//				con.close();
				
			} else if (menu == 3) { // delete
				
				System.out.print("삭제 할 메뉴의 상품코드(PID)을 입력해주세요 : ");
				String pid = sc.nextLine();
				
				
				try {
					int result = dao.delete(pid);
					if (result > 0) {
						System.out.println("입력 완료.");
					}
				} catch (Exception e) {
					e.printStackTrace();
					System.out.println("같은 오류가 반복되면 관리자에게 문의하세요");
				}
				
				
			}
			
			else if (menu == 4) { //update
				
//				con = DriverManager.getConnection(dbURL,dbID,dbPW);
//
//				
//				System.out.print("수정 할 메뉴의 상품코드(PID)을 입력해주세요 : ");
//				String pid = sc.nextLine();
//				System.out.print("수정 할 메뉴의 상품명을 입력하십시오 : ");
//				String pname = sc.nextLine();
//				System.out.print("수정 할 메뉴의 가격을 입력하십시오 : ");
//				int pprice = getValidnum();
//				System.out.print("얼음 추가 가능 유무 (Y, N): ");
//				String iced = sc.nextLine();
//				String sql = "update cafe_menu set pname = ?, pprice = ?, iced = ? where pid = ? ";
//				PreparedStatement pstat = con.prepareStatement(sql);
//				
//				pstat.setString(1, pname);
//				pstat.setInt(2, pprice);
//				pstat.setString(3, iced);
//				pstat.setString(4, pid);
//				
//				
//				int result = pstat.executeUpdate();
//				
//				
//				if(result > 0) {
//					System.out.println("갱신 완료");
//				}else {
//					System.out.println("갱신 실패");
//				}
//
//				con.commit();
//				con.close();
				
			}
			
			else if (menu == 0) {
				System.out.println("프로그램을 종료합니다.");
				System.exit(0);
			} else {
				System.out.println("잘못된 입력입니다.");
			}
			
			
			
		}

	}

}

DAO

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

public class CafemenuDAO { // 데이터 담당 클래스 (Data Access Object)
	
	private String dbURL = "jdbc:oracle:thin:@localhost:1521:xe";
	private String dbID = "kh";
	private String dbPW = "kh";
	
	
	public int insert(String pname, int pprice, String iced) throws Exception{ 
		// 예외를 caller method 에게 전가함 (main에 전가)
		// main 에서 Throws 하게되면 운영체제에 전가 = 예외 발생시 해결 안한다는 소리
		
		Connection con = DriverManager.getConnection(dbURL,dbID,dbPW);
		String sql = "insert into cafe_menu values(cafe_menu_seq.nextval,?,?,?)";
		
		PreparedStatement pstat = con.prepareStatement(sql);
		pstat.setString(1, pname);
		pstat.setInt(2,  pprice);
		pstat.setString(3, iced);
		
		int result =  pstat.executeUpdate();
		
		con.commit();
		con.close();
		return result;
		
		
	}
	public int delete(String pid) throws Exception{
		
		Connection con = DriverManager.getConnection(dbURL,dbID,dbPW);
		String sql = "delete from cafe_menu where pid = ?";
		PreparedStatement pstat = con.prepareStatement(sql);
		pstat.setString(1, pid);
		
		int result = pstat.executeUpdate();
		
		con.commit();
		con.close();
		return result;
	}
	
}