[jsp] JDBC (Java DataBase Connectivity)

bien·2023년 7월 4일
0

jsp

목록 보기
1/1
Connection conn = null;
PreapredStatement pstmt = null;
ResultSet rs = null;
try {
	Class.forName("com.mysql.jdbc.Driver");
	conn = DriverManager.getConnection(dbURL, dbID, dbPassword);
    pstmt = conn.prepareStatement("SELECT * FROM member WHERE email=?");
    pstmt.setString(1, email);
    rs = pstmt.executeQuery();
    if (rs.next()) {
    	member = new Member(rs.getString("email"),
        	rs.getString("password"),
            rs.getString("name"),
            rs.getString("regdate"));
        member.setId(rs.getLong("ID"));
        return member;
     } else {
     	return null;
     }
 } catch (SQLException e) {
 	e.printStackTrace();
    throw e;
 } finally {
            if(rs!=null) try {rs.close();}catch(SQLException ex) {}
            if(pstmt!=null) try{pstmt.close();}catch(SQLException ex) {}
            if(conn!=null) try{conn.close();}catch (SQLException ex) {}
}

국비 교육에서 그저 따라치기만 했던 이 DB연동 코드를 구체적으로 분석해보자!


1. JDBC (Java DataBase Connectivity)란?

의미 그대로 자바에서 DB에 접근하기 위한 연결 방식을 제공하는 API(라이브러리) 이다. 우리는 JDBC를 통해 자바 언어로 데이터베이스에 있는 데이터를 조작할 수 있다.

MySQL, Oracle 등등 다양한 DB는 각기 다른 구조와 특징을 가지고 있어 Java에서 해당 DB의 데이터 접근이 쉽지 않았다. 이런 한계를 극복하고자 JDBC 인터페이스와 클래스를 개발해 통신을 돕는다.

가볍게 요약하자면,Connection, ResultSet, PreparedStatement같은 인터페이스를 각각의 DB에서 구체적으로 구현해 놓았다. 우리는 JDBC의 드라이버를 갈아끼우면서 원하는 DB에 접근하고, 공통적으로 구현되어있는 Connection, ResultSet등 인터페이스의 클래스를 통해 동일한 방식으로 DB를 사용할 수 있다.

  • 각 DB 제조사에서 제공하는 드라이버를 DB에 맞게 설정하면 데이터베이스 접근 방식 외의 모든 작업은 통일된 방법으로 제공
    => DB 제조사마다 드라이버가 다르므로 각각 다운로드 필요
    • ex) MySQL 드라이버: mysql-connector-java.x.x.xx.jar
    • ex) Oracle 드라이버: ojbcX.jar 파일

< JDBC를 활용한 DB 프로그램 구현 4단계 >
1. JDBC 드라이버 로드(드라이버 필요)
2. DB연결(URL, 계정명, 패스워드)
3. PreparedStatement 객체를 통해 SQL 구문 전달 및 실행
4. SQL 구문 실행 후 결과 처리


2. 드라이버 로드

DB와 연결하는 Driver class를 만들 때 반드시 implements해야 하는 interface로 JDBC의 중심이 되는 Interface이다. 기본적으로 JDBC Driver는 각 DB 벤더(vendor. supplier. db회사)들이 제공하며 DB 통신에 필요한 프로토콜, 네트워크 통신, SQL 파싱 및 실행 등의 기능을 제공한다. 우리는 이 드라이버를 통해 자바와 DB사이의 파이프를 연결할 수 있으며, 이 드라이버를 바꿔가며 원하는 DB를 선택할 수 있다.

Class.forName("com.mysql.jdbc.Driver");

try{
    Class.forName("com.mysql.jdbc.Driver");
} catch (Exception e) {
    e.printStackTrace();
}
  • java.lang.Class 클래스의 static 메서드 forName() 메서드 호출
  • 파라미터로 해당 DB의 드라이버 클래스 파일명을 문자열로 전달
    • (패키지명. 클래스명 형태)로 지정
  • 위에서는 MySQL용 JDBC 드라이버를 로드하고 있다.
  • static 메서드로 프로그램 시작 즉시 메모리에 올라가기 때문에 구현 당시 드라이버를 찾지 못하는 ClassNotFoundException 예외 상황을 대비해 try-catch문이 필요하다.

DriverManager에 인스턴스 생성

Class.forName()으로 특정 클래스를 로딩하면 로드될 때 자신의 인스턴스를 생성하고, 자동으로 DriverManager 클래스 메서드를 호출하여 인스턴스를 등록한다. 따라서, 초기에 Class.forName을 통해 클래스를 로딩했으면 다시 로드를 반복할 필요없다.


3. DB연결(URL, 계정명, 패스워드)

Connection

특정 데이터베이스와 연결정보를 가지는 Inteface로, DriverManager로부터 Connection 객체를 가져온다. Connection을 통해 데이터베이스에 대한 연결을 설정하고, SQL문을 실행하며, 결과를 가져 올 수 있다.

DriverManager.getConnection(dbURL, dbID, dbPassword)

try{
    String dbURL = "jdbc:mysql://localhost:3306/java";
    String dbID = "1234";
    String dbPassword="1234";
    conn = DriverManager.getConnection(dbURL, dbID, dbPassword);
} catch (Exception e) {
    e.printStackTrace();
}
  • java.sql.DriverManager 클래스의 static메서드 getConnection()메서드를 호출한다.
    • 파라미터: 해당 DB의 접속 URL, 계정명, 패스워드
    • URL 형식: MYSQL 기준으로 "jdbc:mysql://DB접속주소:포트번호/DB명"
      (당연히 오타나면 안됨)
  • 연결 성공 시 java.sql.Connection 타입 객체가 리턴된다
  • SQLException예외 처리가 필요하다.

4. PreparedStatement 객체를 통해 SQL 구문 전달 및 실행

PreparedStatement

Statemet의 하위 Inteface로 SQL문을 미리 컴파일하여 실행 속도를 높인다는 특징이 있다. 동일한 SQL문이 반복적으로 사용되거나 파라미터를 주입해야 하는 경우 Statement보다 PreparedStatement 사용이 권장된다.

Statement 객체의 SQL은 실행될 때 매번 서버에서 분석되어야 하는 반면, PreparedStatement 객체는 한번 분석되면 재사용이 용이하다는 장점을 가지고 있다.

PreparedStatement 인터페이스는 각각의 인수에 대해 위치홀더(placehodler)를 사용하여 SQL 문장을 정의할 수 있다. 위치홀더는 물음표('?')로 표현된다. 위치홀더는 sql 문장에 나타나는 토큰(Token)인데, 이것은 SQL 문장이 실행되기 전에 실제 값으로 대체된다. 이런 방법을 이용하면 특정 값으로 문자열을 연결하는 방법보다 훨씬 쉽게 SQL 문장을 만들 수 있다.

try {
	String SQL = "SELECT * FROM board WHERE num =?";
    PreparedStatement pstmt = con.prepareStatement(sql);
    pstmt.setInt(1, num);
    rs = pstmt.executeQuery();
}
  • Connection 객체의 prepareStatement()메서드 호출. 파라미터로 실행할 SQL문을 넣어준다.
  • Connection 객체 연결 성공시, java.sql.PreparedStatement 객체가 리턴된다.

executeUpdate vs executeQuery

PreparedStatement객체의 executeXXX() 메서드 호출

  1. executeUpdate(): INSERT, UPDATE, DELETE 구문 실행
    • 실행 후 적용된 레코드수가 int 타입으로 리턴된다.
  2. executeQuery(): SELECT 구문 실행 전용(데이터 조회)
    • 실행 후 조회된 테이블이 ResultSet 타입으로 리턴된다.

5. SQL 구문 실행 후 결과 처리: ResultSet

SQL 구문 실행 결과 처리

SQL문에서 SELECT문을 사용한 질의의 경우 성공 시 결과물로 ResultSet을 반환한다. ResultSet은 SQL 질의에 의해 생성된 테이블을 담고 있다. 또한 ResultSet 객체는 '커서(cursor)'라고 불리는 것을 가지고 있는데, 그것으로 ResultSet에서 특정 행에 대한 참조를 조작할 수 있다.

ResultSet 객체의 next() 메서드는 뒤에 레코드가 존재할 경우 true를 리턴하는는데, while문 혹은 if문을 통해 해당 메서드를 활용하여 결과물을 출력할 수 있다.

while(rs.next()) {
	int idx = rs.getInt("idx");
}

ResultSet의 getXXX(): 데이터 가져오기

  • xxx: 가져올 데이터의 컬럼 타입에 대한 자바 데이터타입명
    • int 타입: getInt()
    • varchar 타입: getString()

📌 Tip

Connection conn = null;
PreapredStatement pstmt = null;
ResultSet rs = null;
try {
	Class.forName("com.mysql.jdbc.Driver");
	conn = DriverManager.getConnection(dbURL, dbID, dbPassword);
    pstmt = conn.prepareStatement("SELECT * FROM member WHERE email=?");
    pstmt.setString(1, email);
    rs = pstmt.executeQuery();
    if (rs.next()) {
    	member = new Member(rs.getString("email"),
        	rs.getString("password"),
            rs.getString("name"),
            rs.getString("regdate"));
        member.setId(rs.getLong("ID"));
        return member;
     } else {
     	return null;
     }
 } catch (SQLException e) {
 	e.printStackTrace();
    throw e;
 } finally {
            if(rs!=null) try {rs.close();}catch(SQLException ex) {}
            if(pstmt!=null) try{pstmt.close();}catch(SQLException ex) {}
            if(conn!=null) try{conn.close();}catch (SQLException ex) {}
}

JAVA로 다양한 회사의 DB에 접근하기 위해, JDBC라는 하나의 추상화가 존재하고, 각 회사는 이 추상화를 구현하여 "드라이버"라는 통로를 제공하고 있다. 개발자는 어떤 드라이버 클래스를 사용할지 선택함으로써 사용할 DB를 선택할 수 있다.

Class.forName("com.mysql.jdbc.Driver");
특정 드라이브의 인스턴스를 생성한다. 고로 초기에 한번 수행하면 된다.

conn = DriverManager.getConnection(dbURL, dbID, dbPassword);
DriverManager로부터 특정 DB의 Connection 객체를 가져온다. Connection을 통해 DB에 연결하고 SQL문을 실행하며, 결과를 가져올 수 있다.

String SQL = "SELECT * FROM board WHERE num =?";
PreparedStatement pstmt = con.prepareStatement(sql);

PreparedStatement를 통해 SQL문을 실행한다.

while(rs.next()) {
	int idx = rs.getInt("idx");
}

ResultSet을 통해 원하는 결과값을 출력한다.


Reference

profile
Good Luck!

0개의 댓글