24일차 JDBC
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 에 접속하기
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 고정
select 문을 쓸때는 Resultset 을 리턴하는 executeQuery 사용
Query 를 전달할 인스턴스 생성
Statement stat = con.createStatement();
// statement 생성
String sql = "Query문 작성";
int result = stat.executeUpdate(sql);
// excuteUpdate 리턴값이 int이다.
Statement 객체란?
- 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;
}
}