多くの場合、基本的なSQLステートメントで多くのデータベースの変更やクエリを実行できることは事実ですが、多くの場合、ベストプラクティスです。 PreparedStatements
を使用することで得られる柔軟性と利点を活用するため 。
標準のJDBCステートメントとPreparedStatement
の主な違い メリットによって最もよく定義されます そのPreparedStatement
あなたとあなたのアプリケーションを提供します。以下では、PreparedStatements
の3つの主要な利点を検証します。 通常のJDBC/SQLステートメントよりも。
SQLインジェクションの防止
PreparedStatement
を使用することの最初の利点 多数の.setXYZ()
を利用できますか .setString()
などのメソッド 、これにより、渡されたSQLステートメント内の引用符などの特殊文字をコードで自動的にエスケープできるため、常に危険なSQL injection
を防ぐことができます。 攻撃。
たとえば、標準のSQLステートメントでは、次のように、ステートメントと直接インラインで値を挿入するのが一般的です。
statement = "INSERT INTO books (title, primary_author, published_date) VALUES ('" + book.getTitle() + "', '" + book.getPrimaryAuthor() + "', '" + new Timestamp(book.getPublishedDate().getTime()) + "'";
これにより、挿入された値から引用符やその他の特殊文字をエスケープしてSQLインジェクションを防ぐために、独自のコードを実行する必要があります。
逆に、PreparedStatement
.setXYZ()
を使用して、次のように呼び出すことができます メソッドの実行中に自動文字エスケープを使用して値を挿入するメソッド:
ps = connection.prepareStatement("INSERT INTO books (title, primary_author, published_date) VALUES (?, ?, ?)");
ps.setString(1, book.getTitle());
ps.setString(2, book.getPrimaryAuthor());
ps.setTimestamp(3, new Timestamp(book.getPublishedDate().getTime()));
ps.executeUpdate();
PreparedStatement
のもう1つの利点 SQL自体がpre-compiled
ということです ステートメントが呼び出されるたびにコンパイルされるのではなく、一度だけシステムによってメモリに保持されます。これにより、特にPreparedStatement
の場合に、より高速な実行が可能になります。 batches
と組み合わせて使用されます 、シリーズを実行できます (またはbatch
)単一のデータベース接続中に一度にすべてのSQLステートメント。
たとえば、ここにList
を受け入れる関数があります 本の。 book
ごとに リストで、INSERT
を実行します ステートメントですが、それらすべてをPreparedStatements
のバッチに追加します。 そして、それらすべてを一挙に実行します:
public void createBooks(List<Entity> books) throws SQLException {
try (
Connection connection = dataSource.getConnection();
PreparedStatement ps = connection.prepareStatement("INSERT INTO books (title, primary_author, published_date) VALUES (?, ?, ?)");
) {
for (Entity book : books) {
ps.setString(1, book.getTitle());
ps.setString(2, book.getPrimaryAuthor());
ps.setTimestamp(3, new Timestamp(book.getPublishedDate().getTime()));
ps.addBatch();
}
ps.executeBatch();
}
}
SQLステートメントへの異常なデータ型の挿入
PreparedStatements
の最後の利点 ここで取り上げるのは、Timestamp
などの異常なデータ型をSQLステートメント自体に挿入する機能です。 、InputStream
、その他多数。
たとえば、PreparedStatement
を使用できます .setBinaryStream()
を使用して、本のレコードにカバー写真を追加します 方法:
ps = connection.prepareStatement("INSERT INTO books (cover_photo) VALUES (?)");
ps.setBinaryStream(1, book.getPhoto());
ps.executeUpdate();