[java] Statement와 PreparedStatement의 차이점

Prepared Statement는 약간 더 강력한 버전의 Statement이며, 최소한 Statement만큼 빠르고 취급하기 쉬워야합니다.
준비된 진술은 매개 변수화 될 수있다

대부분의 관계형 데이터베이스는 다음 네 단계로 JDBC / SQL 쿼리를 처리합니다.

  1. 들어오는 SQL 쿼리 구문 분석
  2. SQL 쿼리 컴파일
  3. 데이터 수집 경로 계획 / 최적화
  4. 최적화 된 쿼리 실행 / 데이터 수집 및 반환

명령문은 데이터베이스에 전송 된 각 SQL 쿼리에 대해 항상 위의 4 단계를 진행합니다. Prepared Statement는 위의 실행 프로세스에서 단계 (1)-(3)을 미리 실행합니다. 따라서, Prepared Statement를 작성할 때 일부 사전 최적화가 즉시 수행됩니다. 그 결과 실행시 데이터베이스 엔진의로드가 줄어 듭니다.

이제 제 질문은 “준비된 진술을 사용하는 다른 이점이 있습니까?”입니다.



답변

의 장점 PreparedStatement:

  • SQL 문의 사전 컴파일 및 DB 측 캐싱은 전체적으로 더 빠른 실행과 동일한 SQL 문을 일괄 적 으로 재사용 할 수있게 합니다 .

  • 내장 된 따옴표 및 기타 특수 문자를 통해 SQL 삽입 공격 을 자동으로 방지 합니다. 이를 위해서는 모든 PreparedStatement setXxx()방법을 사용하여 값을 설정해야합니다.

    preparedStatement = connection.prepareStatement("INSERT INTO Person (name, email, birthdate, photo) VALUES (?, ?, ?, ?)");
    preparedStatement.setString(1, person.getName());
    preparedStatement.setString(2, person.getEmail());
    preparedStatement.setTimestamp(3, new Timestamp(person.getBirthdate().getTime()));
    preparedStatement.setBinaryStream(4, person.getPhoto());
    preparedStatement.executeUpdate();

    따라서 문자열 연결로 SQL 문자열의 값을 인라인 하지 마십시오 .

    preparedStatement = connection.prepareStatement("INSERT INTO Person (name, email) VALUES ('" + person.getName() + "', '" + person.getEmail() + "'");
    preparedStatement.executeUpdate();
  • 하는 SQL 문자열에 비표준 자바 객체의 설정 예 손쉬운 Date, Time, Timestamp, BigDecimal, InputStream( Blob)와 Reader( Clob). 이러한 유형의 대부분 toString()에서는 단순하게 하는 것처럼 “그냥”할 수 없습니다 Statement. PreparedStatement#setObject()아래의 유틸리티 방법에 설명 된 것처럼 루프 내부 에서 사용하도록 리팩터링 할 수도 있습니다.

    public static void setValues(PreparedStatement preparedStatement, Object... values) throws SQLException {
        for (int i = 0; i < values.length; i++) {
            preparedStatement.setObject(i + 1, values[i]);
        }
    }

    다음과 같이 사용할 수 있습니다 :

    preparedStatement = connection.prepareStatement("INSERT INTO Person (name, email, birthdate, photo) VALUES (?, ?, ?, ?)");
    setValues(preparedStatement, person.getName(), person.getEmail(), new Timestamp(person.getBirthdate().getTime()), person.getPhoto());
    preparedStatement.executeUpdate();

답변

  1. 사전 컴파일 (한 번)되므로 동적 SQL을 반복적으로 실행하기 위해 더 빠릅니다 (매개 변수 변경)

  2. 데이터베이스 명령문 캐싱으로 DB 실행 성능 향상

    데이터베이스는 이전에 실행 된 명령문에 대한 실행 계획 캐시를 저장합니다. 이를 통해 데이터베이스 엔진은 이전에 실행 된 명령문에 대한 계획을 재사용 할 수 있습니다. PreparedStatement는 매개 변수를 사용하므로 매개 변수가 실행될 때마다 동일한 SQL로 표시되므로 데이터베이스는 이전 액세스 계획을 재사용하여 처리를 줄입니다. 명령문은 매개 변수를 SQL 문자열에 “인라인”하므로 DB에 동일한 SQL로 표시되지 않으므로 캐시 사용이 금지됩니다.

  3. 이진 통신 프로토콜은 DB 서버에 대한 더 적은 대역폭과 더 빠른 통신 호출을 의미합니다

    준비된 문은 일반적으로 비 SQL 이진 프로토콜을 통해 실행됩니다. 즉, 패킷에 데이터가 적으므로 서버와의 통신 속도가 빠릅니다. 일반적으로 네트워크 작업은 인 메모리 CPU 작업보다 속도가 느린 디스크 작업보다 속도가 느립니다. 따라서 네트워크를 통해 전송되는 데이터 양을 줄이면 전체 성능에 좋은 영향을 미칩니다.

  4. 제공된 모든 매개 변수 값에 대해 텍스트를 이스케이프하여 SQL 삽입을 방지합니다.

  5. 쿼리 코드와 매개 변수 값 (연결된 SQL 문자열과 비교)을보다 강력하게 분리하여 가독성을 높이고 코드 관리자가 쿼리의 입력 및 출력을 빠르게 이해할 수 있도록합니다.

  6. Java에서는 getMetadata () 및 getParameterMetadata ()를 호출하여 각각 결과 세트 필드 및 매개 변수 필드에 반영 할 수 있습니다.

  7. Java에서는 setObject, setBoolean, setByte, setDate, setDouble, setDouble, setFloat, setInt, setLong, setShort, setTime, setTimestamp를 통해 Java 객체를 매개 변수 유형으로 지능적으로 받아들입니다. () 형식).

  8. Java에서는 setArray 메소드를 통해 매개 변수 유형으로 SQL ARRAY를 승인합니다.

  9. Java에서는 setClob / setNClob, setBlob, setBinaryStream, setCharacterStream / setAsciiStream / setNCharacterStream 메소드를 통해 CLOB, BLOB, OutputStream 및 Reader를 매개 변수 “feeds”로 각각 승인합니다.

  10. Java에서는 setURL, setRowId, setSQLXML 및 setNull 메소드를 통해 DB 특정 값을 SQL DATALINK, SQL ROWID, SQL XML 및 NULL에 설정할 수 있습니다.

  11. Java에서는 Statement의 모든 메소드를 상속합니다. addBatch 메소드를 상속하며 addBatch 메소드를 통해 일괄 처리 된 SQL 명령 세트와 일치하도록 매개 변수 값 세트를 추가 할 수 있습니다.

  12. Java에서는 특수 유형의 PreparedStatement (서브 클래스 CallableStatement)를 사용하여 고성능, 캡슐화, 절차 적 프로그래밍 및 SQL 지원, DB 관리 / 유지 보수 / 논리 로직, 독점 DB 로직 및 기능 사용을 지원하는 스토어드 프로 시저를 실행할 수 있습니다.


답변

PreparedStatementSQL 인젝션 공격 을 막는 데 아주 좋은 방어책 입니다. 바인딩 매개 변수 값은 “작은 바비 테이블” 을 방지하여 원치 않는 방문을 방지 하는 좋은 방법 입니다.


답변

Statement에 비해 PreparedStatement의 장점은 다음과 같습니다.

  1. PreparedStatement는 특수 문자를 자동으로 이스케이프하므로 SQL 주입 공격을 방지하는 데 도움이됩니다.
  2. PreparedStatement를 사용하면 매개 변수 입력으로 동적 조회를 실행할 수 있습니다.
  3. PreparedStatement는 조회에 대한 입력 매개 변수를 설정하기 위해 다른 유형의 세터 메소드를 제공합니다.
  4. PreparedStatement가 Statement보다 빠릅니다. PreparedStatement를 재사용하거나 여러 쿼리를 실행하기 위해 일괄 처리 방법을 사용할 때 더 잘 보입니다.
  5. PreparedStatement는 setter 메소드를 사용하여 객체 지향 코드를 작성하는 데 도움이되는 반면 Statement를 사용하면 쿼리를 생성하기 위해 String Concatenation을 사용해야합니다. 설정할 매개 변수가 여러 개인 경우 문자열 연결을 사용하여 쿼리를 작성하면 매우보기 흉하고 오류가 발생하기 쉽습니다.

SQL 주입 문제에 대한 자세한 내용은 http://www.journaldev.com/2489/jdbc-statement-vs-preparedstatement-sql-injection-example참조하십시오.


답변

추가 할 것이 많지 않습니다.

1-루프에서 (1 회 이상) 쿼리를 실행하려는 경우 언급 한 최적화로 인해 준비된 명령문이 더 빠를 수 있습니다.

2-매개 변수화 된 쿼리는 SQL 삽입을 피하는 좋은 방법입니다. 매개 변수화 된 쿼리는 PreparedStatement에서만 사용 가능합니다.


답변

진술은 정적이며 준비된 진술은 동적입니다.

명령문은 DDL에 적합하며 DML에 대한 준비된 통계입니다.

준비된 진술은 더 빠르지 만 진술은 느립니다.

더 많은 차이점 (아카이브)


답변

명령문에서 CLOB를 수행 할 수 없습니다.

그리고 : (OraclePreparedStatement) ps