Day 27. JDBC 1 ( 자바에서 DB사용하기 )

ho_c·2022년 3월 27일
0

국비교육

목록 보기
27/71
post-thumbnail
post-custom-banner

JDBC 첫 번째 시간

[ 여기까지 온 이유 ]

처음 프로그램을 만들 때, DTO 인스턴스를 생성해 데이터를 넣고 ArrayList 에 주소를 저장했다.
이 방식은, RAM에 데이터를 저장하기 때문에 프로그램의 종료와 함께 데이터도 사라졌다.

곧, 데이터의 영구적 보관이 우리에게 놓인 문제였다.

문제의 해결법은 보조 기억 장치에 영구적으로 보관하는 것이었다.
그 방법론으로 첫 번째로 본 것이 File IO 방식이다.
그러나 위 방식은 보안, 중복, 무결성, 버그 등 문제가 많기에 안전한 데이터 보관을 위해 DB라는 파일 형식에 저장하게 되었다.
따라서 이를 조작, 관리하기 위해 DBMS라는 미들웨어의 사용법인 SQL을 배웠다.

따라서 이젠 프로그램을 통해 입력받는 데이터 저장 및 관리를 위해 DBMS와 우리가 자바로 만들 프로그램을 연결하고자 한다.

📝목차

  1. JDBC
  2. 응용

1. JDBC

자바에서 DB에 접속할 수 있도록 하는 API이다.
응용프로그램과 DBMS 간의 통신을 중간에서 번역해준다.
사용하는 데이터베이스 종류와 상관없다.

1) 외부라이브러리 불러오기

Properties -> Java Build Path -> Classpath -> Add External JARs...

DBMS는 데이터를 관리하는 하나의 서버이다. 따라서 자바 프로그램으로 DB를 이용하려면,
File IO에서 배운 것처럼 서로의 네트워크 프로토콜을 따라야 한다.

그러나 이는 쉬운 일이 아니고, 우리가 굳이 알 필요가 없다.
왜냐면 오라클에서 그 프로토콜을 이용할 수 있는 라이브러리를 제공해준다.
좀 더 정확히 말하면 JDBC에 연결되는 자사 프로그램의 드라이버 클래스를 제공한다.


2) 예외 전가, 예외 책임

JDBC를 통해서 DB와 연결하기 전에, 한 가지 설정을 다시 봐야 한다.

  • 예외 전가 : Callee 가 Caller에게 예외를 떠넘기는 것이다.
  • 예외 책임 : 예외 발생 시 어떻게 처리할 것인지 설정하는 것이다.

위 차이는 불리는 메서드(Callee) 부르는 메서드(Caller)의 차이에서 발생한다.
Callee 는 단순 작업만 하면 된다. 예외가 발생한다면 불린 그 자리에서 처리하는 것이다.

주로 Caller인 main에서 처리해주면 된다.
물론 메서드가 메서드를 호출할 때도 있는데, 그것도 마찬가지로 Caller에서 처리한다.
따라서 메서드를 호출하는 Main에서 try-catch로 예외 책임을 지고 어디에도 불리지 못하는 main은 예외 전가를 해선 안 된다.


3) 개발 과정

① 드라이버 로드

오라클에서 제공한 DBMS 드라이버를 인스턴스를 생성한다.
이를 통해 DBMS와 연결이 된다.
Class.forName("oracle.jdbc.driver.OracleDriver"); // Reflection API

Reflection 기법으로 오라클 드라이버 JVM에 띄워둔다.
이때, 해당 클래스가 없을 수도 있기에 예외가 발생하니 처리하도록 한다.

② 접속 : Connection

DB 접속을 위해, 계정과 비밀번호, URL를 입력하는 과정
Connection con = DriverManager.getConnection("URL", "ID", "PW"); 

DriverManager 를 통해 DBMS 서버에 접근해 로그인되면 Connection 이라는 연결 인스턴스가 반환된다.
이제 연결을 통해 우리가 DB 개발도구처럼 워크시트를 생성해서 쿼리를 입력하고
반환을 받게 된다.

③ 워크시트 생성 : Statement

Statement 는 쿼리를 입력하는 워크시트 인스턴스이다.
Statement stat = con.createStatement();

④ SQL 입력

생성된 워크시트 인스턴스를 가지고 쿼리를 입력하고 DB를 동작할 수 있다.
int result 
= stat.executeUpdate("insert into cafe_menu values(cafe_seq.nextval, 'Americano', 1500, 'Y')");

// 쿼리 결과 확인
if (result > 0) {
				System.out.println("쿼리 성공");
			}

executeUpdate 메서드는 insert, update, delete처럼 실 DB에 영향을 주는 쿼리에서 사용한다.
따라서 성공 시, 그 결과를 int값으로 반환하고 이를 활용하여 콘솔로 결과를 받아볼 수 있다.

⑤ Commit;

java8 부터는 자동 커밋을 지원한다.
하지만 insert, update, delete와 같이 DB에 실 영향을 주는 쿼리는 트랜잭션에 그 명령이 묶여있어서 commit 을 해줘야 한다.

con.commit();

⑥ 로그아웃

DBMS라는 서버는 기본 동접 100명 정도 유지하는데, 이 접속은 프로그램을 종료한다고 해서 함께 종료되는 것이 아니다.
따라서 응용프로그램 쪽에서 해당 Connection 연결을 닫아줘야 한다.

con.close();

2. 응용

이제 위의 개발 과정을 통해서 DML을 응용해보자.

1) ETC

insert, update, delete는 쿼리문의 차이만 있을 뿐이다.
그리고 DB에 영향을 주기 때문에 executeUpdate를 사용한다.

① insert

Connection con = DriverManager.getConnection("URL", "ID", "PW");
		
Statement stat = con.createStatement();
			
int result = stat.executeUpdate("insert into cafe_menu values(1, 'Americano', 1500, 'Y')");

if (result > 0) {
    System.out.println("쿼리 성공");
	} 

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

② update

int result 
	= stat.executeUpdate("update cafe_menu set pname='Cafe Latte', pprice=3000 where pid=1011");
			
if(result>0) {
	System.out.println("쿼리 성공");
	}

③ delete

int result = stat.executeUpdate("delete from cafe_menu where PID=1012");

if (result>0) {
	System.out.println("쿼리 성공");
	}

2) selecet

앞선 DML은 DB에 반영된 작업의 성공수를 int값으로 반환한다.
하지만 결과를 출력하는 용도로 사용하는 select은 작업의 성공이 아닌
결과를 반영해야 하는데, int로 반영하면 우리는 알 수 없다.

따라서 select은 작업결과를 ResultSet(결과집합) 이라는 인스턴스로 반환한다.

ResultSet

  • 데이터 자체가 아닌 주소값으로 쉽게 말하면 select으로 출력된 데이터의 주소값을 가지고 있는 객체이다.
  • 즉, 포인터로 처음 있는 주소는 쿼리 결과의 헤더 라인의 주소를 가지고 있다.
  • 결과로 이동하려면 .next(); 를 이용해 다음 데이터의 주소로 간다.
  • 주소를 가지고 접근하기 때문에 DB와 연결을 끊으면 안 된다.

.next();

  • boolearn을 반환한다.
  • 기능은 2가지이다.
    ① 다음 행을 가리키는 기능
    ③ 가리키는 행에 데이터의 유무
  • 데이터가 없으면 false를 반환하는데, 이를 이용해 반복문을 돌려 출력할 수 있다.
Statement state = con.createStatement();
		 
String sql =  "select * from cafe_menu"; 

ResultSet rs =  state.executeQuery(sql); // 데이터에 영향을 미치지 않는 쿼리는 executeQuery을 사용

while(rs.next()) { // next로 확인되는 데이터가 있는 동안 반복
		int pid = rs.getInt("pid"); // pid컬럼값을 int로 꺼내오겠다.
		String pname = rs.getString("pname");
		int pprice = rs.getInt("pprice");
		String iced = rs.getString("iced");
				
		System.out.println(pid + " : " + pname + " : " + pprice + " : " + iced);
		}

con.close();

이제 DB를 통해서 데이터를 입력하고 검색하고 수정할 수 있고 프로그램이 꺼져도 사라지지 않게 되었다.

다음 시간엔 JDBC로 main에 작성된 코드들을 DAO로 메서드 단위로 빼는 리팩토링을 해보도록 하자.

profile
기록을 쌓아갑니다.
post-custom-banner

0개의 댓글