[JAVA] Oracle JDBC

쥬니·2022년 10월 6일
2

공부

목록 보기
6/11

❗ 개인적으로 공부했던 내용을 복습하고 정리하기 위한 글입니다! 따라서 내용이 정확하지 않을 수 있습니다!

Java DataBase Connectivity : 자바에서 데이터베이스에 접속할 수 있도록 하는 자바 API

📦 Oracle에 계정 및 테이블 추가

eclipse에서 JDBC를 사용하기 전에, 로컬 Oracle 데이터 베이스에 JDBC계정과 TEST테이블을 추가하였다.

CREATE USER JDBC IDENTIFIED BY JDBC;
GRANT CONNECT, RESOURCE TO JDBC;

CREATE TABLE TEST (
    TNO NUMBER,
    TNAME VARCHAR2(20),
    TDATE DATE
);


테이블이 잘 만들어졌고,

데이터도 잘 넣어 두었다.

🔧 JDBC 라이브러리 추가

먼저 JDBC를 사용하기 전에 프로젝트 파일에 JDBC 라이브러리를 추가하여 주었다. 오라클 JDBC를 사용하였고, 이를 eclipse의 build path에 추가하여 주었다.
Project -> Properties -> Java Build Path -> Libraries -> Add External JARs 에서 ojdbc6.jar가 있는 경로를 찾아, 해당 파일을 추가하여 주었다!


프로젝트 폴더의 .classpath을 확인해 보면 5번째 줄과 같이 라이브러리 추가가 잘 된 것을 확인할 수 있다!

🧾 JDBC 사용

JAVA 프로젝트에서 JDBC 사용을 하려면 다음과 같은 처리를 해주어야 한다.

  1. 필요한 변수 생성
  2. JDBC Driver 등록
  3. Connection 생성
  4. Statement 생성
  5. SQL문을 전달하면서 실행
  6. 결과를 받아서 VO객체에 담거나, 트랜잭션 처리
  7. 다 쓴 JDBC용 객체들의 자원 반납


뭐가 이렇게 많은지... 코드로 보면서 정리해 보자.

0. 필요한 변수 생성

먼저 SELECT 구문을 생성하기 위해서 Connection과, Statement, SELECT 구문의 결과를 받을 ResultSet 객체를 생성한 뒤, 사용할 sql구문을 문자열로 선언하여 주었다.

Connection conn = null;
Statement stmt = null;
ResultSet rset = null;
		
String sql = "SELECT * FROM TEST";

Connection 객체 : DB의 연결정보를 담고있는 객체
Statement 객체 : 해당 DB에 SQL문을 전달하고 실행한 후 결과를 받아내는 객체
ResultSet 객체 : 만일 실행한 SQL문이 SELECT문일 경우 조회된 결과들이 담겨있는 객체

1. JDBC Driver 등록

JDBC Driver를 Class.forName()를 통해 등록하여 준다. 이때 try-catch문이 없으면 컴파일 오류가 나기 때문에 try-catch문 안에 선언하여 준다.

try{
	Class.forName("oracle.jdbc.driver.OracleDriver");
} catch (ClassNotFoundException e) {
	e.printStackTrace();
}

2. Connection 생성

JDBC Driver를 등록하였으면 Connection을 생성하여준다. 우리는 conn이라는 객체를 생성해두었는데, 이 안에 Connection을 생성하여 줄 것이다. 이 또한 try-catch문이 없으면 컴파일 오류가 발생하기 때문에, 위에 쓴 try문에 Connection 코드를, catch문에 SQLException 처리를 해준다.

try{
	conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe", "JDBC", "JDBC");		// 접속할 DB의 url, id, password를 입력하여 준다.
} catch (SQLException e) {
	e.printStackTrace();
}

3. Statement 생성

Connection 생성이 완료되었다면, Statement를 생성해준다. try문 안에서 conn생성하는 줄 아래에 선언해주면 된다.

stmt = conn.createStatement();

4. SQL문을 전달하면서 실행

SELECT절의 결과는 ResultSet이다. 위에서 우리는 ResultSet 객체를 생성해뒀으니, 해당 객체에 결과를 받아주면 된다. executeQuery()메소드의 반환형은 ResultSet이다.

rset = stmt.executeQuery(sql);

5. 결과를 받아서 VO객체에 담거나, 트랜잭션 처리

SELECT문의 경우 결과를 받아서 출력하거나, VO객체에 담는다. 트랜잭션 처리는 후술할 예정이지만 SELECT를 제외한 DML문에서 처리해줘야 한다. (INSERT, UPDATE, DELETE)
해당 예제에서는 단순히 ResultSet을 콘솔창에 출력해 주었다.

while(rset.next()) {
	int tNo = rset.getInt("TNO");
	String tName = rset.getString("TNAME");
	Date tDate = rset.getDate("TDATE");

	System.out.println(tNo +  ", " + tName + ", " + tDate);

}


DB에 있는 데이터들이 잘 SELECT되어 콘솔창에 출력되었다!

출력하기 위해서 반복문 안에 next()메소드를 사용하였는데, 이 메소드는 ResultSet의 커서를 하나씩 아래로 이동시켜주는 역할을 한다. 또한 해당 행이 존재하면 true를, 없다면 false를 반환하여 준다. 따라서 ResultSet의 끝까지 반복하면서 데이터들을 출력하였다.

6. 다 쓴 JDBC용 객체들의 자원 반납

가장 중요하다!!! Scanner클래스를 다 사용하였다면 close()메소드를 사용한 것 처럼, JDBC도 자원 반납을 해주어야 한다. 자원반납을 해주는 위치는 finally문에서 하면 된다. 또한 close()메소드를 사용하기 위해서는 try-catch문이 필요하고, 생성의 역순으로 자원반납을 해주어야 한다!

finally {
		try {
			rset.close();
			stmt.close();
			conn.close();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

JDBC SELECT 전체 코드

JDBC를 통해 SELECT하는 전체 코드는 다음과 같다.

  		Connection conn = null;
		Statement stmt = null;
		ResultSet rset = null;
		
		String sql = "SELECT * FROM TEST";
		
		try {
        	Class.forName("oracle.jdbc.driver.OracleDriver");
			conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe", "JDBC", "JDBC");
			stmt = conn.createStatement();
			rset = stmt.executeQuery(sql);

			while(rset.next()) {
				
				int tNo = rset.getInt("TNO");
				String tName = rset.getString("TNAME");
				Date tDate = rset.getDate("TDATE");
				
				System.out.println(tNo +  ", " + tName + ", " + tDate);
				
			}
			
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}  finally {
			try {
				rset.close();
				stmt.close();
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			
		}

5_2. 트랜잭션 처리

만약 내가 사용할 쿼리가 INSERT, UPDATE, DELETE라면 조금 다르게 처리해주어야 한다. 실행할 쿼리가 다음과 같다면, 트랜잭션 처리를 해주어야 한다.

String sql = "INSERT INTO TEST VALUES(50, '쥬니쥬니', SYSDATE)";

해당 구문은 INSERT문이기 때문에 Statement의 executeUpdate()메소드를 사용해야 하며, 반환형은 int형이다. 이것은 DML을 오라클에서 실행하면 n행이 실행되었다고 나오는데, 여기서 n이 반환값이 된다고 보면 된다.

int result = stmt.executeUpdate(sql);

이렇게 DML문을 사용하였으면 트랜잭션 처리를 해주어야 한다. result의 값이 0보다 크면 쿼리문이 실행된 것이고, 그렇지 않다면(물론 실행되어서 0행이 실행되었습니다. 하고 뜨겠지만...) 쿼리문이 제대로 실행되지 않은 것이다. 따라서 조건문으로 간단히 트랜잭션을 처리하여 준다.

if( result > 0 ) {
	conn.commit();
} else {
	conn.rollback();
}

나머지 부분들은 SELECT와 마찬가지로 작성해주면 된다.

JDBC INSERT 전체 코드

int result = 0;
Connection conn = null;
Statement stmt = null;

String sql = "INSERT INTO TEST VALUES(50, '쥬니쥬니', SYSDATE)";
	
try {
			
	Class.forName("oracle.jdbc.driver.OracleDriver");
	System.out.println("driver 등록 성공!!");

	conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe", "JDBC", "JDBC");
	System.out.println("Connection 객체 생성!");

			
	stmt = conn.createStatement();
	System.out.println("Statement 객체 생성!");

	result = stmt.executeUpdate(sql);

	if (result > 0) { // 성공했을 경우 commit
		conn.commit();
	} else { // 실패했을 경우 rollback
		conn.rollback();
	}
} catch (ClassNotFoundException e) {
		e.printStackTrace();
} catch (SQLException e) {
		e.printStackTrace();
} finally {
		try {
			stmt.close();
			conn.close();
		} catch (SQLException e) {
				e.printStackTrace();
		}

}

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


콘솔에 다음과 같이 나오고,

DB에 잘 등록된 걸 확인할 수 있다!

📖 마치며

포스팅이 늦어진 계기... 그것은 맥북에어(M2)와 오라클의 싸움에서 제가 새우등이 터져 피눈물을 흘렸기 때문입니다... 회고에서도 쓸 거지만 도커는 도대체 어떻게 쓰는 것이며 오라클 클라우드는 왜 나의 회원가입을 입구컷 했던 것일까...
더이상 포스팅을 지체할 수 없어서 윈도우 환경에서 했던 걸 포스팅 했습니다! JDBC... 회사에서는 이런 방법 말고 xml파일로 만들어 쿼리문을 날리곤 했는데, 뭔가 기초부터 다시 탄탄히 배우니까 지식의 깊이가 깊어져감을 느꼈습니다. 또한, 이제 본격적으로 MVC패턴에 맞추어 프로젝트를 만들고 하는 게 좋았습니다! 여기에 적응해는 저를 발견 할 수 있었습니다
아무튼 그럼 다시 오라클과 맥북에어의 싸움을 붙이러...
끝! 😉

0개의 댓글