티스토리 뷰

- JDBC (Java DataBase Connectivity)

자바를 이용해서 DB를 다루기 위한 API.

각 DB 벤더들마다 JDBC 인터페이스를 구현한 드라이버를 제공한다.

 

- JDBC 사용법: 안드로이드에서 SQLite 쓸 때나 PHP에서 MySQL 쓸 때 어떻게 했는지 떠올려보자. 비슷하다.

1) JDBC 드라이버 설치 및 Import

Maven에 의존성을 추가해서 쉽게 드라이버 라이브러리를 다운로드받을 수 있다.

 

<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.45</version>
</dependency>

다운로드 받았으면 .java (혹은 .jsp) 파일에서 -> import java.sql.*

 

2) 연결 (Connection)

드라이버를 로드하고, 드라이버 매니저를 이용해 Connection 인스턴스를 얻는다.

이때 DB의 URL과 DB 유저네임, 패스워드가 필요하다.

 

Class.forName("com.mysql.jdbc.Driver"); // JDBC 드라이버를 로드한다
String db_url = "jdbc:mysql://localhost/test_db"; // 내 컴퓨터의 MySQL 서버의 test_db라는 DB에 접속
Connection con = DriverManager.getConnection(db_url, id, pwd); // Connection 객체를 얻는다

 

3) SQL 다루기

Connection.createStatement() 를 이용해 Statement 객체를 얻고, Statement 객체의 내장 함수들을 이용해 쿼리를 실행할 수 있다.

> Statement.execute(sql): 아무 SQL문이나 넣을 수 있다

> Statement.executeQuery(sql): SELECT문을 쓸 때 사용

> Statement.executeUpdate(sql): INSERT, UPDATE, DELETE문을 쓸 때 사용

 

PreparedStatement라는 것도 있다. 이건 Connection.prepareStatement(sql) 로 얻으며, 얻은 PrepareStatement 객체의 set 메서드들을 이용해서 물음표 안에 변수를 넣을 수가 있다.

넣은 다음엔 executeQuery() 를 하면 된다.

 

쿼리 실행 결과는 ResultSet이라는 객체를 이용해서 받는다.

> getInt, getString 등 타입에 맞게

> 인자로는 컬럼명이나 숫자 (몇번째 컬럼을 가져올 것인지) 를 넣어주면 됨

 

ResultSet rs = statement.executeQuery( "select no from user" );
while ( rs.next() )
 System.out.println( rs.getInt( "no") );

 

4) 연결 닫기

DB 사용을 마쳤으면 연결을 닫아준다. 별로 안 중요하다고 생각할 수도 있지만 이걸 제대로 안해주면 DB 서버가 접속자 수 제한에 걸릴 수도 있음.

 

> ResultSet.close()

> Statement.close()

> Connection.close()

 

- JDBC 실습

1) Role.java: Role 객체에 대한 생성자와 getter/setter 메서드를 정의한 클래스

 

> DTO (Data Transfer Object): 로직을 가지지 않는 순수한 데이터 객체로, 필드와 getter/setter 메서드를 가짐. 추가적으로 toString() 이나 equals() 같은 메서드를 오버라이딩하기도 한다.

 

package kr.or.connect.jdbcexam.dto; // 이렇게 별도의 패키지로 관리할 수 있다

public class Role {
 private Integer roleId;
 private String description;

// Role 객체에 대한 생성자
 public Role() { }
 public Role(Integer roleId, String description) {
   super();
   this.roleId = roleId;
   this.description = description;
 }

// getter, setter 메서드들. 이런건 직접 키보드로 치지 않고 이클립스 기능으로 자동으로 만들 수 있다
 public Integer getRoleId() { return roleId; }
 public void setRoleId(Integer roleId) { this.roleId = roleId; }
 public String getDescription() { return description; }
 public void setDescription(String description) { this.description = description; }

// Role 객체의 내용을 출력할 때 좀 더 보기 좋으라고 만들어준다
 @Override
 public String toString() {
   return "Role [roleId=" + roleId + ", description=" + description + "]";
 }
}

2) RoleDao.java

> DAO (Data Access Object): 데이터를 조회하거나 조작하는 기능을 전담하도록 만든 객체.

 

package kr.or.connect.jdbcexam.dao;
 
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
 
import kr.or.connect.jdbcexam.dto.Role; // Role 클래스를 쓰기 위해 Role.java를 import
 
public class RoleDao {
// URL, 유저네임, 패스워드는 getRole 뿐 아니라 다른 메서드들에서도 계속 쓰일 것이기 때문에 지역변수가 아니라 클래스 멤버변수로 선언해둔다
private static String dburl = "jdbc:mysql://localhost/db_test";
private static String dbUser = "user";
private static String dbpasswd = "password";
 
 public Role getRole(Integer roleId) {
  Role role = null; // Role 객체
  Connection conn = null;
  PreparedStatement ps = null; // 그냥 Statement와 다르게 PreparedStatement는 WhereClease를 사용가능
  ResultSet rs = null;
 
  try {
   Class.forName("com.mysql.jdbc.Driver");
   conn = DriverManager.getConnection(dburl, dbUser, dbpasswd);
   // 안드로이드에서와 마찬가지로 물음표를 사용해서 SQL문 안에 변수를 넣어줄 수 있다
   String sql = "SELECT description,role_id FROM role WHERE role_id = ?"; 
   ps = conn.prepareStatement(sql);
   ps.setInt(1, roleId); // 물음표 안에 변수를 세팅해주려면 이렇게 한다. 1은 몇번째 물음표인지를 의미
   rs = ps.executeQuery();
 
   if (rs.next()) {
    String description = rs.getString(1); // 컬럼 인덱스는 0이 아니라 1부터 시작한다는 점 유의
    int id = rs.getInt("role_id");
    role = new Role(id, description); // Role.java에 만들어놨던 Role 생성자를 이용해 Role 객체 생성
   }
  } catch (Exception e) {
   e.printStackTrace();
  } finally { // finally를 사용해서 항상 close가 실행되게 한다
   if (rs != null) { // 단, ResultSet이 null인데 rs.close() 를 하면 그것대로 오류가 발생하므로 그런 경우 제외
    try {
     rs.close();
    } catch (SQLException e) { // 예외처리를 해주는 것이 중요하다
     e.printStackTrace();
    }
   }
  if (ps != null) {
   try {
    ps.close();
   } catch (SQLException e) {
    e.printStackTrace();
   }
  }
  if (conn != null) {
   try {
    conn.close();
   } catch (SQLException e) {
    e.printStackTrace();
   }
  }
 }
 
return role;
}
}

3) jdbcExam1.java: 메인 프로그램

 

package kr.or.connect.jdbcexam;
 
import kr.or.connect.jdbcexam.dao.RoleDao;
import kr.or.connect.jdbcexam.dto.Role;
 
public class JDBCExam1 {
 public static void main(String[] args) {
  RoleDao dao = new RoleDao(); // DAO 객체 생성
  Role role = dao.getRole(100); // Role 번호 100번에 해당하는 Role을 가져온다
  System.out.println(role); // Role.java의 toString() 에 정의해놨던 형식대로 출력됨. 어떤 원리?
 }
}

> DAO, DTO, VO에 대해서는 학부 때 겉핥기로 배운 적은 있는데 코드로 어떻게 구현되는지는 이제 알았다... Spring 프레임워크에 대해서 배울 때 다시 나올 것.

 

> DB 작업을 하다보면 드라이버를 로드해서 Connection 객체를 얻고, 연결을 닫아주는 등 반복적인 작업을 하는 코드들이 많아지게 되는데 프레임워크를 쓰면 이런 반복 작업들은 프레임워크가 알아서 해준다고 한다.

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함