[Java] 자바 이클립스 JDBC 5. Statement와 PreparedStatement 비교



Statement와 PreparedStatement의 차이

1) 보안

    Statement: 

    - 사용자가 입력한 값을 가지고 SQL문을 만들기 때문에 보안이 취약하다.

    - 즉 악의적으로 SQL의 일부를 포함하는 값을 입력할 수 있다.

    PreparedStatement

    - ?(in-parameter) 자리에 임의의 SQL문을 삽입할 수 없다.

    - 삽입해봐야 단순 문자열로 취급한다.

    - 그래서 보안 문제를 발생시키지 않는다.

2) 바이너리 데이터

    Statement

    - 문자열로 SQL문을 만들기 때문에 바이너리 데이터를 삽입할 수 없다.

    PreparedStatement

    - ?(in-parameter) 자리에 바이너리 데이터를 삽입할 수 있다.

3) 코드의 가독성

    Statement

    - + 연산자를 사용하여 컬럼의 값을 연결하는 식으로 문자열을 만들기 때문에,

      컬럼의 개수가 많으면 문자열을 붙이는 코드도 산만해지고 복잡해진다.

    PreparedStatement

    - setXxx()를 사용하여 값을 넣기 때문에 코드가 간결하다.

4) 실행속도

    서버에 SQL문을 전달하기 전에 서버에서 원하는 형식으로 변환하여 보낸다.

    단순히 SQL을 한 번만 실행한다면 Statement나 PreparedStatement 둘 다 속도가 같다.

    그러나 같은 SQL문을 값을 바꿔가면서 여러 번 실행할 경우,

    PreparedStatement는 SQL문을 컴파일한 후 값만 넣어서 보내기 때문에 속도가 빠르다.

   Statement는 executeXxx()를 실행할 때마다 SQL문을 매번 컴파일하기 때문에 속도가 느리다.

      



JDBC 프로그래밍: PreparedStatement 객체 사용 후

 - 더하기 연산자를 사용하여 SQL문을 만드는 대신,

   in-parameter '?' 를 사용하여 SQL 문을 만든다.



JDBC SQL에서 PreparedStatement의 사용 예제


import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
public class Test05_2 {
  public static void main(String[] args) throws Exception {
    // 원래는 값을 JVM 아규먼트나 프로그램 아규먼트 등 외부로부터 받아야 하지만,
    // 테스트를 원활하게 하기 위해서 변수에 값을 담아 놓자!
   
    String jdbcDriver = "com.mysql.jdbc.Driver";
    String jdbcUrl = "jdbc:mysql://localhost:3306/데이터베이스명";
    String jdbcUsername = "유저명";
    String jdbcPassword = "1111";
   
    String name = "홍길동102";
    String email = "hong102@test.com";
    String tel = "1111-1111";
    String password = "1111";
    try {
      Class.forName(jdbcDriver);
    } catch (Exception e) {
      e.printStackTrace();
    }
   
    try (
      Connection con = DriverManager.getConnection(jdbcUrl, jdbcUsername,jdbcPassword);
       
      // SQL 문을 미리 작성해둔다. 값(문자, 숫자 상관없이)이 들어갈 자리는 ?을 사용하여 비워둔다.
      // 이때 ?를 in-parameter라 부른다.
      // preparedStatement()의 리턴 값은 java.sql.PreparedStatement의 구현체이다.
    PreparedStatement stmt = con.prepareStatement("insert into memb(name, tel, email, pwd) values(?,?,?,password(?))");
    ) {
     
    // SQL문을 서버에 보내기 전에 in-parameter 자리에 값을 채운다.
    // 컬럼의 타입에 따라 호출하는 메서드가 다르다.
    // => setXxx(컬럼인덱스, 값)
    // => 컬럼 인덱스는 1부터 시작한다.
    // 빈자리(in-parameter)에 값을 넣을 때 컬럼의 순서를 지킬 필요는 없다.
    // 그렇다고 굳이 임의 순서대로 넣는 것은 코드의 이해도를 떨어뜨린다.
    stmt.setString(1, name);
    stmt.setString(2,  tel);
    stmt.setString(3, email);
    stmt. setString(4, password);
    // 이렇게 setXxx()를 호출하여 SQL 문을 완성하면,
    // + 연산자를 사용하여 SQL문을 완성하는 방법보다 편리하고 가독성이 좋다.
   
    // 위에서 SQL문을 준비하고 값을 채웠기 때문에 여기에서는 그냥 실행만 하면 된다.
   
    int count = stmt.executeUpdate("insert into memb(name, tel, email, pwd) values('" +
      name + "', '"+
      tel + "', '"+
      email + "', password('" +
      password + "'))");
     
    System.out.println(count);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

}



블로그 이미지

필로그래머

,

[Java] 자바 이클립스 JDBC 프로그래밍 : MySQL JDBC Type 4 드라이버 다운로드



1.

JDBC 프로그래밍 : MySQL JDBC Type 4 드라이버 다운로드

 - 절차

1) www.mvnrepository.com에 들어가 mysql을 검색한다.

2) MySQL Connector/J의 Gradle 의존 라이브러리 정보를 복사한다.

3.) 프로젝트 폴더에 있는 build.gradle 파일에서 dependencies {}를 선언해 

    블록 안에 복사한 정보를 붙여 넣는다.

4) 명령창(cmd)을 실행하고 java01 프로젝트 폴더에서 gradle 명령을 실행한다.

> gradle eclipse

5) 이클립스에서 프로젝트 폴더를 "Refresh(F5)" 한다

6) 드라이버 라이브러리 파일(mysql-connector-java-5.1.42.jar)에 있는 클래스를 로딩해본다.



2.
JDBC 프로그래밍: DriverManager 클래스
  - JDBC 드라이버를 관리하는 객체
  - 이 객체에 JDBC 드라이버 객체를 등록해야만 사용할 수 있다.
  - DBMS에 연결할 때도 이 객체가 필요하다.


DriverManager에 MySQL을 등록하는 예제

 * => JDBC 드라이버를 관리하는 객체
 * => 이 객체에 JDBC 드라이버 객체를 등록해야만 사용할 수 있다.
 * => DBMS에 연결할 때도 이 객체가 필요하다.
 */
import java.sql.DriverManager;
import java.sql.SQLException;
public class Test01_2 {
  public static void main(String[] args) throws Exception {
    // 1) MySQl JDBC 드라이버의 정보를 다루는 객체를 생성한다.
    //    => 이 객체를 통해 MySQL DMBS에 연결할 수 있다.
    com.mysql.jdbc.Driver mysqlDriver = new com.mysql.jdbc.Driver();
   
    // 2) MySQL JDBC 드라이버를 "드라이버 관리자"에 등록한다.
    //    => 반드시 java.lang.Driver 규칙에 따라 만든 클래스여아 한다.
    DriverManager.registerDriver(mysqlDriver);
   
    // 3) 드라이버 관리자를 통해 DBMS와 연결한다.
    //    => 직접 MySQL 드라이버를 사용하지 않고,
    //       이렇게 DriverManager 클래스를 통해 우회하여 DBMS와 연결한다.
    //    => 이렇게 우회하는 이유? 특정 DBMS에 종속되지 않기 위함이다.
    //       자바 코드를 작성할 때 특정 DBMS에서만 유효한 코드를 작성하게 되면,
    //       그 DBMS에 종속되게 되고 유지보수가 힘들어진다.
    //    => DriverManager의 getConnection()을 호출하여 DMBS와 연결한다.
    //       리턴 값은 DBMS와의 연결 정보를 갖고 있는,
    //       java.sql.Connection 규격에 따라 만든 객체이다.
   
    java.sql.Connection con = DriverManager.getConnection(
        "jdbc:mysql://localhost:3306/데이터베이스명" /* 연결할 DMBS와 데이터베이스 정보 */
        "유저아이디", /* 해당 DB를 사용할 수 있는 아이디*/
        "사용자 암호" /* 사용자 암호 */);
   
    // 4) 연결이 되었다는 걸 표시해보자
    System.out.println("DBMS와 연결되었음!");
  

  }


- 실행 결과 : 

Fri May 26 16:50:04 KST 2017 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.

DBMS와 연결되었음!




3.

JDBC 프로그래밍: Statement 객체

 - Statement 객체는 Connection 객체로부터 얻는다.

 - SQL문을 DBMS에 전달하는 일을 한다.

   SELECT 문을 실행한 경우, 그 결과를 다루는 객체를 리턴한다.

 


Statement 객체를 만들고 결과값을 받는 ResultSet 객체를 

생성하는 예제를 위 예제에 추가한다.


// 5) SQL을 실행할 Statement 객체 얻기

    //    => java.sql.Statement 규격에 따라 만든 객체를 리턴한다.
    java.sql.Statement stmt = con.createStatement();
   
    // 6) SELECT SQL문을 DBMS에 보낸다.
    //    => Statement 객체가 SELECT 문을 DBMS에 보내는 일을 한다.
    //    => SQL을 문자열 그대로 보내는 것이 아니라,
    //       DBMS가 처리하기 쉬운 형태로 변환(컴파일)하여
    //       그 변환된 SQL을 DBMS에 보낸다.
    //    => 물론 DBMS 마다 그 변환 형식이 다를 것이다.
    //       변환하는 일은 각 DBMS의 JDBC 드라이버 클래스들 중에서
    //       Statement 객체가 할 것이다.
    //    => 주요함수
    //       executeQuery() : select 문을 보낼 때
    //       executeUpdate() : insert, update, delete 등 기타 SQL을 보낼 때
    //    => executeQuery()의 리턴 값
    //       서버가 SELECT을 실행한 후 준비한 결과 값을 가져오는 도구를 리턴한다.
    //    => 그 도구는 java.sql.ResultSet 규격에 따라 만든 객체이다.
    java.sql.ResultSet rs = stmt.executeQuery("select 컬럼명1, 컬럼명2, 컬럼명3, 컬럼명4 from 테이블명 ");
   
    // 7) ResultSet 객체를 통해 서버에 결과를 한 개씩 가져온다
    //    => 한꺼번에 다 가져오는 것이 아니라, 한 개씩 가져온다.
    //    => next() : 서버에서 결과를 한 개 가져온다.
    while (rs.next()) {
      // 서버에서 가져온 한 개의 레코드 값은 ResultSet 객체에 보관되어 있다.
      // 꺼내보자!
      System.out.printf("%d, %s, %s, %s\n",
          rs.getInt("컬럼명1"),
          rs.getString("컬럼명2"),
          rs.getString("컬럼명3"),
          rs.getString("컬럼명4"));
    }
   
    // 8) 지금까지 사용한 JDBC 관련 객체의 자원을 해제한다.
    //     => ResultSet을 더 이상 사용하지 않으면 자원을 해제하라!
    rs.close();
    //     => Statement를 더 이상 사용하지 않으면 자원을 해제하라!
    stmt.close();
    //     => DBMS와 연결을 끊고 싶다면 Connection의 close()을 호출하라!
    con.close();
   
    // => DriverManager는 close() 메서드가 없다.
  }



블로그 이미지

필로그래머

,