Statement와 PreparedStatement의 차이점

자바 탑

방금 Spring 5 및 Spring Boot 2의 기본 사항에 초점을 맞춘 새로운 Learn Spring 과정을 발표했습니다 .

>> 과정 확인

1. 개요

이 튜토리얼에서는 JDBC의 StatementPreparedStatement 인터페이스 의 차이점을 살펴볼 것 입니다. 저장 프로 시저를 실행하는 데 사용되는 JDBC API 인터페이스 인 CallableStatement 는 다루지 않습니다 .

2. JDBC API 인터페이스

계산서의 PreparedStatement는 SQL 쿼리를 실행하는 데 사용할 수 있습니다. 이러한 인터페이스는 매우 유사합니다. 그러나 기능과 성능이 서로 크게 다릅니다.

  • 문자열 기반 SQL 쿼리 를 실행하는 데 사용됩니다.
  • PreparedStatement매개 변수화 된 SQL 쿼리를 실행하는 데 사용됩니다.

예제에서 StatementPreparedStatement 를 사용할 수 있도록 pom.xml 파일 에서 h2 JDBC 커넥터를 종속성으로 선언 합니다.

 com.h2database h2 1.4.200 

이 기사 전체에서 사용할 엔티티를 정의 해 보겠습니다.

public class PersonEntity { private int id; private String name; // standard setters and getters }

3. 진술

첫째, Statement 인터페이스는 문자열을 SQL 쿼리로 받아들입니다. 따라서 SQL 문자열을 연결 하면 코드의 가독성이 떨어집니다 .

public void insert(PersonEntity personEntity) { String query = "INSERT INTO persons(id, name) VALUES(" + personEntity.getId() + ", '" + personEntity.getName() + "')"; Statement statement = connection.createStatement(); statement.executeUpdate(query); }

둘째, SQL 인젝션에 취약합니다 . 다음 예는 이러한 약점을 보여줍니다.

첫 번째 줄에서 업데이트는 모든 행의 " name "열을 " hacker "로 설정합니다. "—"뒤의 모든 내용은 SQL에서 주석으로 해석되고 update 문의 조건이 무시되기 때문입니다. 두 번째 줄에서는 " name "열의 따옴표 가 이스케이프 되지 않았기 때문에 삽입이 실패합니다 .

dao.update(new PersonEntity(1, "hacker' --")); dao.insert(new PersonEntity(1, "O'Brien"))

셋째, JDBC는 인라인 값이있는 쿼리를 데이터베이스에 전달합니다 . 따라서 쿼리 최적화가 없으며 가장 중요한 것은 데이터베이스 엔진이 모든 검사를 보장해야한다는 것 입니다. 또한 쿼리는 데이터베이스에 동일하게 표시되지 않으며 캐시 사용을 방지합니다 . 마찬가지로 일괄 업데이트는 별도로 실행해야합니다.

public void insert(List personEntities) { for (PersonEntity personEntity: personEntities) { insert(personEntity); } }

넷째, 인터페이스는, ALTER 및 DROP을 CREATE 같은 DDL 쿼리에 적합합니다 :

public void createTables() { String query = "create table if not exists PERSONS (ID INT, NAME VARCHAR(45))"; connection.createStatement().executeUpdate(query); }

마지막으로, 인터페이스를 저장하고 파일과 배열을 검색에 사용할 수 없습니다 .

4. PreparedStatement

첫째, PreparedStatementStatement 인터페이스를 확장합니다 . 파일 및 배열을 포함하여 다양한 개체 유형을 바인딩하는 방법이 있습니다. 따라서 코드는 이해하기 쉬워 집니다 .

public void insert(PersonEntity personEntity) { String query = "INSERT INTO persons(id, name) VALUES( ?, ?)"; PreparedStatement preparedStatement = connection.prepareStatement(query); preparedStatement.setInt(1, personEntity.getId()); preparedStatement.setString(2, personEntity.getName()); preparedStatement.executeUpdate(); }

둘째, 제공된 모든 매개 변수 값에 대한 텍스트를 이스케이프하여 SQL 삽입으로부터 보호합니다 .

@Test void whenInsertAPersonWithQuoteInText_thenItNeverThrowsAnException() { assertDoesNotThrow(() -> dao.insert(new PersonEntity(1, "O'Brien"))); } @Test void whenAHackerUpdateAPerson_thenItUpdatesTheTargetedPerson() throws SQLException { dao.insert(Arrays.asList(new PersonEntity(1, "john"), new PersonEntity(2, "skeet"))); dao.update(new PersonEntity(1, "hacker' --")); List result = dao.getAll(); assertEquals(Arrays.asList( new PersonEntity(1, "hacker' --"), new PersonEntity(2, "skeet")), result); }

셋째, PreparedStatement 는 사전 컴파일을 사용 합니다. 데이터베이스가 쿼리를 받으면 쿼리를 사전 컴파일하기 전에 캐시를 확인합니다. 따라서 캐시되지 않은 경우 데이터베이스 엔진은 다음 사용을 위해 저장합니다.

또한 이 기능 은 비 SQL 바이너리 프로토콜을 통해 데이터베이스와 JVM 간의 통신 속도를 높 입니다. 즉, 패킷에 데이터가 적기 때문에 서버 간의 통신이 더 빨라집니다.

넷째, PreparedStatement 는 단일 데이터베이스 연결 중에 일괄 실행을 제공합니다 . 이것이 실제로 작동하는지 봅시다 :

public void insert(List personEntities) throws SQLException { String query = "INSERT INTO persons(id, name) VALUES( ?, ?)"; PreparedStatement preparedStatement = connection.prepareStatement(query); for (PersonEntity personEntity: personEntities) { preparedStatement.setInt(1, personEntity.getId()); preparedStatement.setString(2, personEntity.getName()); preparedStatement.addBatch(); } preparedStatement.executeBatch(); }

다음으로 PreparedStatementBLOBCLOB 데이터 유형 을 사용하여 파일을 저장하고 검색하는 쉬운 방법을 제공합니다 . 같은 맥락에서 java.sql.Array 를 SQL Array 로 변환하여 목록을 저장하는 데 도움이됩니다 .

마지막으로 PreparedStatement 는 반환 된 결과에 대한 정보를 포함하는 getMetadata () 와 같은 메서드를 구현합니다 .

5. 결론

이 튜토리얼에서는 PreparedStatementStatement 의 주요 차이점을 설명했습니다 . 두 인터페이스 모두 SQL 쿼리를 실행하는 메서드를 제공하지만 DDL 쿼리 에는 Statement 를 사용 하고 DML 쿼리에는 PreparedStatement 를 사용하는 것이 더 적합 합니다.

평소와 같이 모든 코드 예제는 GitHub에서 사용할 수 있습니다.

자바 바닥

방금 Spring 5 및 Spring Boot 2의 기본 사항에 초점을 맞춘 새로운 Learn Spring 과정을 발표했습니다 .

>> 과정 확인