-> 블로그 이전

[Java] JDBC 실행 순서 정리

2022. 3. 5. 20:40Language`/Java

"일단 JDBC Interface를 사용하려면 JDBC Driver가 필요하다"

1. 각 DBMS에 알맞은 드라이버를 구글링을 통해서 다운로드한다

2. 다운로드 후, 해당 드라이버를 자바 프로젝트 상에 적용시켜줘야 한다

 


현재 "sample" DB내의 "user" 테이블 현황

CREATE TABLE user(
    idx INT NOT NULL AUTO_INCREMENT,
    name VARCHAR(20) NOT NULL,
    gender CHAR(2) NOT NULL,
    bth DATE NOT NULL,
    PRIMARY KEY(idx)
) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4;


1. 드라이버 로드

- DBMS에 맞는 드라이버를 다운로드하면 해당 드라이버를 로드해줘야 한다

Class.forName("[드라이버]");

- Class.forName()은 동적으로 JDBC 드라이브 클래스를 로드해주는 코드이다

  1. 지정한 드라이브 클래스가 객체화
  2. DriverManager.registerDriver()를 호출해서 드라이버 리스트에 등록된다

Oracle 드라이버

"oracle.jdbc.driver.OracleDriver"

>> Class.forName("oracle.jdbc.driver.OracleDriver");

MySQL 드라이버

// 예전 Version
"com.mysql.jdbc.Driver"

// 최신 Version
"com.mysql.cj.jdbc.Driver"

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

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

MaridDB 드라이버

"org.mariadb.jdbc.Driver"

>> Class.forName("org.mariadb.jdbc.Driver");

 


 

2. DB연결을 위한 Connection 객체 생성

- 최근에는 Connection 객체 생성 단계에서 Class.forName()까지 같이 수행해주기 때문에 따로 Class.forName()을 작성할 필요가 없다

Connection con = DriverManager.getConnection(url, user, pwd);

url

- 해당 DB의 URL을 작성해야 한다

- 해당 DB의 위치

 

※ 오라클

"jdbc:oracle:thin:@[IP]:[포트 번호]:[서비스 이름]

IP : 로컬에 DB가 저장되어 있으면 "localhost"라고 작성하면 된다

포트 번호 : 오라클 DB의 포트 번호 :: default = 1521

서비스 이름(SID) : DB를 식별할 수 있는 이름

>> "jdbc:oracle:thin:@localhost:1521:orcl"

>> "jdbc:oracle:thin:@192.168.0.10:1521:xe"

 

MySQL

"jdbc:mysql://[IP]:[포트번호]/[DB이름]"

>> "jdbc:mysql://localhost:3306/test"

>> "jdbc:mysql://192.168.0.10:3306/sample"

 

MariaDB

"jdbc:mariadb://[IP]:[포트번호]/[DB이름]"

>> "jdbc:mariadb://localhost:3307/test"

>> "jdbc:mariadb://192.168.0.10:3307/sample"

 

user

- DB의 계정명

 

pwd

- 해당 DB의 계정의 비밀번호

 

// Oracle Version
Connection con = DriverManager.getConnection(
    "jdbc:oracle:thin:@localhost:1521:orcl" // url
    "test" // id
    "1234" // pwd
}

// MySQL Version
Connection con = DriverManager.getConnection(
    "jdbc:mysql://localhost:3306/sample" // url
    "test" // id
    "1234" // pwd
}

// MariaDB Version
Connection con = DriverManager.getConnection(
    "jdbc:mariadb://localhost:3307/sample" // url
    "test" // id
    "1234" // pwd
}

 


 

3. SQL 쿼리문 & 실행

- 요청할 SQL문을 전송할 때 필요하다

 

1) 정적인 쿼리문 Statement

Statement stmt = con.createStatement();

- 단일로 사용할 때 속도가 빠르다

- 쿼리에 인자를 부여할 수 없다

- 매번 컴파일을 수행해야 한다

  1. 쿼리 문장 분석
  2. 컴파일
  3. 실행
String url = "jdbc:mysql://localhost:3306/sample";
String user = "test";
String pwd = "1234";

Connection con = DriverManager.getConnection(url, user, pwd);
// getConnection을 통해서 자동적으로 Class.forName()까지 수행
Statement stmt = con.createStatement();

String sql = "SELECT * FROM user;"; // 정적인 SQL 쿼리문
ResultSet rs = stmt.executeQuery(sql); // SQL 쿼리문에 대한 결과값 저장

while(rs.next()){ // 결과값에서 ROW별로 순차적으로 가져오기
    int idx = rs.getInt("idx");
    String name = rs.getString("name");
    String gender = rs.getString("gender");
    Date birth = rs.getDate("bth");
    // ROW의 각 COLUMN의 타입에 맞게 필드값 가져오기

    System.out.println("## " + idx);
    System.out.println("name : " + name);
    System.out.println("gender : " + gender);
    System.out.println("birthday : " + birth);
}

-  Statement는 정적인 SQL 쿼리문을 통해서 해당 쿼리문에 대한 결과를 가져와야 한다

  • 정적인 SQL 쿼리문 : 그 자체로 완성된 쿼리문

- ResultSet을 통해서 해당 SQL 쿼리문의 결과를 저장한다

  • 여기서 next()는 해당 결과를 ROW별로 가져올 수 있다
    • ROW의 각 COLUMN의 타입에 맞게 필드값을 가져와야 한다
    • getInt("[컬럼명]"); / getString("[컬럼명]"); / getDate("[컬럼명]");
    • 여기서 컬럼명은 대소문자를 구분하지 않는다
  • get~()는 컬럼의 순서로도 지정할 수 있는데 컬럼의 첫번째는 1부터 시작한다

 

 

2) 동적인 쿼리문 PreparedStatement

PreparedStatement pstmt = con.preparedStatement();

- 쿼리에 인자를 부여할 수 있다

- 처음 컴파일된 후, 이후에는 컴파일을 수행하지 않는다

- 여러번 수행될 때 속도가 빠르다

- 가독성이 좋다

- 기존 Statement보다 성능이 좋다

 

>> 사용자의 입력값으로 쿼리를 생성할 경우 사용한다

String url = "jdbc:mysql://localhost:3306/sample";
String user = "test";
String pwd = "1234";

Connection con = DriverManager.getConnection(url, user, pwd);
// getConnection을 통해서 자동적으로 Class.forName()까지 수행

String sql = "SELECT * FROM user WHERE idx BETWEEN ? AND ?";
// 동적인 SQL 쿼리문
// 사용자가 "?" 부분에 적절한 값을 넣어줘야 완성된 SQL 쿼리문이 된다
PreparedStatement pstmt = con.prepareStatement(sql);

pstmt.setInt(1, 1);
pstmt.setInt(2, 3);
// "?" 부분에 값을 채워넣는 코드

ResultSet rs = pstmt.executeQuery();

while(rs.next()){ // 결과값에서 ROW별로 순차적으로 가져오기
    int idx = rs.getInt("idx");
    String name = rs.getString("name");
    String gender = rs.getString("gender");
    Date birth = rs.getDate("bth");
    // ROW의 각 COLUMN의 타입에 맞게 필드값 가져오기

    System.out.println("## " + idx);
    System.out.println("name : " + name);
    System.out.println("gender : " + gender);
    System.out.println("birthday : " + birth);
}

- 동적인 SQL 쿼리문에는 "?"라는 미지의 값을 설정해줘야 한다

  • 이 값은 User가 원하는 값으로 설정해줘야 한다

- pstmt.set~~('파라미터인덱스', '값')으로 설정해줘야 한다

  • '파라미터인덱스'는 동적인 SQL 쿼리문의 "?"의 인덱스를 나타낸다
    • 만약 pstmt.setIint(2, 3)이면 동적인 SQL쿼리문의 두번째 "?"에 '3'이라는 값을 넣겠다는 것이다


Statement의 execute~()

- SELECT 요청의 경우 executeQuery(String sql)을 통해서 요청해야 한다

  • return값은 ResultSet "Set" 개념으로 각 ROW별로 return된다

- INSERT/UPDATE/DELETE의 경우 executeUpdate(String sql)를 통해서 요청해야 한다

  • return값은 해당 테이블에서 변경된 ROW의 수만큼 return된다

 

PreparedStatement의 execute~()

- PreparedStatement의 경우 미리 컴파일 한 후, "?"의 값만 변경해서 재사용하기 때문에 execute~()에 인자가 존재하지 않는다