OracleDB/OracleDB 국비지원 수업 정리

OracleDB 4일차 수업내용
깝몬 2023. 6. 5. 18:16

메서드를 통한 DML의 간편화

 

저번시간에 우리가 작성한 Java DB 연동 코드는  Main Method 내에 모든것을 작성하는 것이기 때문에 메인 메서드가 어떻게 작동하는지 살펴보려면 시간이 많이 걸리며 수정이 어려웠다.

 

하지만 우리는 어떠한 작동 과정을 메서드로 미리 작성하여 간단한 구문으로 main메서드에서 작동하도록 하려고 하며, Select, 상세Select, Insert, Delete, Update 의 기능들도 미리 메서드로 구현하여 편하게 사용 할 수 있도록 하려고 한다.

 

 String url = "jdbc:oracle:thin:@172.30.1.68:1521/xe"; // 1521은 설치하면서 저장해둔것 확인
     String user = "scott";
     String password = "tiger";
     Connection conn = null;

먼저 필드를 선언해준다. user와 password, url이 main메서드와 다른 메서드에서도 쓰이고자 하면 이것을 미리 말해주고 시작하면 모두에게 적용할수 있기때문이다.

 

1. JDBC등록과 Connection얻기를 한동작으로

 

public void getDBConnection() {

    //1. JDBC Driver등록
     try {
        Class.forName("oracle.jdbc.OracleDriver");
        System.out.println("jdbc 등록완료!");
    } catch (ClassNotFoundException e1) {
        e1.printStackTrace(); // 못찾으면 여기 진행
    }

    //2. 연결 Connection 얻기

     try {
     //return 값을 받아줄 변수를 만들자
        conn = DriverManager.getConnection(url, user, password); 
        System.out.println("getConnection 성공!");
    } catch (SQLException e) {
        System.out.println("getConnection 실패!");
        e.printStackTrace();
    }
}

 

이 곳에서는 큰 설명이 필요하지 않을것으로 보인다. 어제 배운 내용으 그대로 가져와 실행해도 큰 문제가 없다.

 

2. CRUD메서드들 미리 선언하기

우리는 CRUD메서드를 선언하기에 앞서서 Statment와 PreparedStatement 라는 두 클래스의 차이를 구분할 필요가 있다.

 

1. Statement
변형이 없는 SQL문을 실행할때 사용

객체생성에 parameter를 요구하지 않는다.

비교적 가벼운 구조를 가지고 있으나, 구조가 경직되어있다. 가독성이 좋지않다.

2. PreparedStatement
?(bounding variable)를 사용하는 SQL구문에 사용
다만 execute 하기전에 set method들을 이용하여 순서대로 bounding variable에 들어갈 내용을 작성 해주어야만 한다.

객체생성할때 실행에 필요한 SQL구문을 String 타입 paramter로 요구한다.

상대적으로 무거운 속도를 가지나 변수를 변경하여 작동시키기 좋아 유연한 구조를 가진다. 가독성이 좋다.

볼드처리된 부분을 중요하게 살펴보자. 나는 저 두부분을 구별하지 못해 많은 에러를 만났다... 

 

따라서 우리는 2개의 statement 객체를 준비하겠다.

 

     Statement stmt = null;
     PreparedStatement stmt2 = null;
     ResultSet rst = null;

 

 

 

1. parameter를 받지 않는crud 메서드

 

// 조회메서드
public void getDeptList() throws SQLException {

    stmt = conn.createStatement();

             String sql = "select deptno, dname, loc from dept";
             rst = stmt.executeQuery(sql);
             System.out.println("★★★★목록조회결과");

             while(rst.next()) {
                 int deptno = rst.getInt(1);
                 String dname = rst.getString(2);
                 String loc = rst.getString(3);
                 System.out.printf("%d\t\t%s\t\t%s\n" ,deptno, dname, loc);
                 rst.getInt("deptno");
                 System.out.println();

             }
             if(rst!=null) {rst.close();}
             boolean rs = stmt2.execute(sql);	//업데이트 된 열의 개수만큼을 int값으로 return!
             if(rs) {System.out.println(rs+"!");}
             else {System.out.println("쿼리가 아무것도 안했다!");}

    }
		
// 입력메서드
public void insertDept() throws SQLException {
     int inputDno = 78;
     String inputDname = "부서연습";
     String inputLoc = "목동";
     String sql = "insert into dept(deptno, dname, loc)"
     +"values(?,?,?)"; 

     stmt2 = conn.prepareStatement(sql);

     stmt2.setInt(1, inputDno);
     stmt2.setString(2, inputDname);
     stmt2.setString(3, inputLoc);
     stmt2.executeUpdate();
     System.out.println(inputDno+inputDname+inputLoc+"을 입력했습니다.");
}

// 삭제메서드
public void deleteDept() throws SQLException {
    stmt = conn.createStatement();
    String sql = "DELETE DEPT "
            + "WHERE DEPTNO = 94";
    int cnt = stmt2.executeUpdate(sql);	//업데이트 된 열의 개수만큼을 int값으로 return!
    if(cnt!=0) {System.out.println(cnt+"만큼 쿼리로 변경!");}
    else {System.out.println("쿼리가 아무것도 안했다!");}
}
// 수정메서드
public void updateDept() throws SQLException {
     Statement stmt = null;
        stmt = conn.createStatement();


         String sql = "UPDATE DEPT "
                    + "SET LOC = '갱냄', DNAME = 'B팀'"
                    + "WHERE DEPTNO = 99";
         int cnt = stmt.executeUpdate(sql);	//업데이트 된 열의 개수만큼을 int값으로 return!
         if(cnt!=0) {System.out.println(cnt+"만큼 쿼리로 변경!");}
         else {System.out.println("쿼리가 아무것도 안했다!");}

}

?를 사용하는경우와 사용하지 않는 경우가 보일것이다. 입력하는 메서드를 제외하면 실질적으로 더러운 sql구문이 작성 될 일이 없어 모두 statement를 이용했다.

 

 

2. parameter를 받는 crud 메서드

 

//상세수정 메서드
public void updateDeptLocByNumber(int inputDno, String inputDname, String inputLoc) throws SQLException {
    String sql = "UPDATE DEPT "
                    + "SET dname=?, loc=? "
                    + "WHERE DEPTNO=?";
    stmt2 = conn.prepareStatement(sql);
    stmt2.setString(1, inputDname);
    stmt2.setString(2, inputLoc);
    stmt2.setInt(3, inputDno);
    int cnt = stmt2.executeUpdate();	//업데이트 된 열의 개수만큼을 int값으로 return!
    if(cnt!=0) {System.out.println(cnt+"만큼 쿼리로 변경!");}
    else {System.out.println("쿼리가 아무것도 안했다!");}
}
// 상세조회메서드
public void getDeptListByDnum(int deptno1) throws SQLException {
     String sql = "select deptno, dname, loc "
                + "FROM dept "
                + "where deptno = ?";

     stmt2 = conn.prepareStatement(sql);

     stmt2.setInt(1, deptno1);
     rst = stmt2.executeQuery();

     while(rst.next()) {
         int deptno = rst.getInt(1);
         String dname = rst.getString(2);
         String loc = rst.getString(3);
         System.out.printf("%d\t\t%s\t\t%s\n" ,deptno, dname, loc);
         System.out.println();
     }
     if(rst!=null) {rst.close();}
}
//상세 삭제 메서드
public void deleteDeptByDnum(int Dnum) throws SQLException {
    String sql = "DELETE DEPT "
            + "WHERE DEPTNO=?";

    stmt2 = conn.prepareStatement(sql);
    stmt2.setInt(1, Dnum);

    int cnt = stmt2.executeUpdate();
    if(cnt!=0) {System.out.println(cnt+"만큼 쿼리로 삭제!");}
    else {System.out.println("쿼리가 아무것도 안했다!");}
}
// 상세입력 메서드
public void insertMyDept(int inputDno, String inputDname, String inputLoc) throws SQLException {
    String sql = "insert into dept(deptno, dname, loc)"
             +"values(?,?,?)"; 

    stmt2.setInt(1, inputDno);
    stmt2.setString(2, inputDname);
    stmt2.setString(3, inputLoc);
    stmt2 = conn.prepareStatement(sql);
    stmt2.executeUpdate();
    System.out.println(inputDno+" "+inputDname+" "+inputLoc+"을 입력했습니다.");
}

후자의 경우 코드를 작성하기 조금 더 복잡 할 수 있으나 직접 우리가 parameter만 수정한다면 main메서드에서 쉽게 이들을 이용할 수 있다.

 

 

3. 사용한 자원 반납

// 자원반납메서드(Connection 만 닫자)
		public void connectionClose() {
			try{if(conn!=null) {conn.close();System.out.println("자원반납성공");}}
			catch(SQLException e) {e.printStackTrace();System.out.println("자원반납실패");}
		}

 

이 또한 긴 설명이 필요하지는 않다.

 

 

 

QUERY문의 연산/ 비교 / 정렬

크기비교 연산자

기준은 왼쪽의 수이다.

동일하다 =
같지않다 !=
<>
크다(초과) >
작다(미만) <
이상 >=
이하 <=

 

예시

SELECT * FROM DEPT
WHERE DEPTNO>60;

DEPT에서 DEPTNO가 60초과인 모든 ROW를 가져와라!

 

예시2

SELECT * FROM DEPT
WHERE COMM IS NULL;

NULL 값을 찾기위해서는 COLUMN명 IS NULL 의 문법으로 작성해주면 된다.

 

논리연산자

논리 합 AND
논리 곱 OR
하나라도 일치하는지 IN( , , ..)
하나도 일치안하는 NOT IN (  ,  ,  ...)
사잇값
(NUM1 이상 NUM2 이하)
BETWEEN  NUM1 AND NUM2

예시

SELECT * FROM DEPT
WHERE DEPTNO IN (10, 30);

DEPT에서 DEPTNO가10 또는 30인 ROW를 가져와라!

 

 

 

 

예시2

SELECT FROM DEPT
WHERE NOT IN(10,30);

DEPT에서 DEPNTO가 10, 30 중 아무것도 아닌 ROW를 가져와라!

 

예시3

SELECT *
FROM DMP
WHERE HIREDATE BETWEEN '1992-01-01' AND '1993-01-01';

날짜를 쓸 경우 작은 따옴표안에 'YYYY-MM-DD' 를 통해 날짜를 비교하여 사용 한다.

이 외에도 다른 양식을 사용하여 'YY-MM-DD' 꼴로 표현해도 동일하다.

 

 

정렬(오름차순,내림차순)

오름차순 정렬 order by [비교 column명]
내림차순 정렬 order by [비교 column명] desc

숫자가 올 경우 오름차순은 작은 수부터, 내림차순은 큰 수부터 출력

알파벳이나 한글은 오름차순은 앞 글자부터(A부터 / ㄱ부터..), 내림차순은 뒷글자부터 (Z부터 / ㅎ부터..)

 

예시

select *
from emp
order by sal;

emp 테이블의 모든 데이터를 sal값의 오름차순(ascending order)에 따라 row를 정렬하여 조회

 

 

예시2

select *
from emp
order by sal desc;

emp 테이블의 모든 데이터를 sal값의 내림차순(descending order)에 따라 row를 정렬하여 조회

 

 

시퀀스

시퀀스 생성

문법

create sequence 시퀀스명
[increment by 증감]
[start with 시작번호]
[minvalue 최솟값]
[maxvalue 최댓값]
[nocycle | cycle]
[nocache | cache];

직관적으로 보이지 않는 요소들에 대해서만 설명을 하겠다.

cycle은 최대, 최소숫자에 도달했을때 반복하여 다시 처음의 숫자로 돌아갈 지를 뜻한다.

cache는 메모리의 활용성을 위하여 계속적으로 메모리에 접근하여 새로운 숫자를 할당 받는것이 아니라, 미리 일정분량의 숫자를 할당해두어 숫자에 대한 접근성을 높이는 방식이며, 그 할당되는 수의 개수를 지정한다.

 

 

예시

create sequence seqdno
increment by 1
start with 49
[maxvalue 99
nocycle;

 

 

 

시퀀스 수정

문법

alter  sequence 시퀀스명
[increment by 증감]
[minvalue 최솟값]
[maxvalue 최댓값]
[nocycle | cycle]
[nocache | cache];

 

 

예시

alter sequence seq_dno
increment by -1
minvalue 20
maxvalue 80
cycle;

 

 

 

시퀀스 사용

1. NEXTVAL

문법

INSERT INTO TABLE명(COLUMN명)
VALUES(sequence명.NEXTVAL);

 

예시

INSERT INTO DEPT(DEPTNO)
VALUES(seq_dno.NEXTVAL);

sequence의 수를 다음수로 올리며 그 숫자를 return 한다.

 

 

2. CURRVAL

문법

INSERT INTO TABLE명(COLUMN명)
VALUES(sequence명.CURRENTVAL);

 

예시

INSERT INTO DEPT(DEPTNO)
VALUES(seq_dno.CURRENTVAL);

sequence의 현재수를 return하며 sequence의 숫자가 변하지 않는다.

 

 

시퀀스 삭제

문법

drop sequence 시퀀스명;

 

예시

drop sequence seq_dno;

 

 

 

Eclispse에서 자바메서드에서 Sequence를 작동시켜보기

?로 우리가 직접 매번 바꾸어주던 번호를 sql 내에서 sequence 생성 후 메서드 실행문을 변형했다.

 

작성 해준 메서드를 메인메서드에서 삽입 시켜보자.

 

메인메서드내에 삽입해준 위의 메서드

이제 이대로 컴파일시킨 후 sql창에서 입력이 잘 되었는지 확인해보자.

 

정상적으로 실행 된것이 보인다.

 

이런식으로 구문의 문법만 맞는다면 우리는 이클립스에서도 DB와의 연동을 편하게 할 수 있다.