Database
 sql >> Datenbank >  >> RDS >> Database

Der Unterschied zwischen einer JDBC-Anweisung und einer vorbereiteten Anweisung

Es stimmt zwar, dass in vielen Fällen eine einfache SQL-Anweisung viele Datenbankänderungen oder -abfragen erledigt, aber es ist oft eine beste Vorgehensweise um die Flexibilität und Vorteile zu nutzen, die Ihnen durch die Verwendung von PreparedStatements geboten werden .

Die Hauptunterschiede zwischen einer standardmäßigen JDBC-Anweisung und einer PreparedStatement lassen sich am besten durch die Vorteile definieren dass ein PreparedStatement bietet Ihnen und Ihrer Anwendung. Im Folgenden untersuchen wir die drei Hauptvorteile von PreparedStatements über normale JDBC/SQL-Anweisungen.

SQL-Einschleusungsschutz

Der erste Vorteil der Verwendung eines PreparedStatement So können Sie die Vielzahl von .setXYZ() nutzen Methoden wie .setString() , wodurch Ihr Code Sonderzeichen wie Anführungszeichen innerhalb der übergebenen SQL-Anweisung automatisch mit Escapezeichen versehen kann, wodurch die immer gefährliche SQL injection verhindert wird Angriff.

Beispielsweise kann es in einer Standard-SQL-Anweisung typisch sein, Werte direkt in die Anweisung einzufügen, etwa so:

statement = "INSERT INTO books (title, primary_author, published_date) VALUES ('" + book.getTitle() + "', '" + book.getPrimaryAuthor() + "', '" + new Timestamp(book.getPublishedDate().getTime()) + "'";

Dies würde Sie dazu zwingen, Ihren eigenen Code auszuführen, um SQL-Injections zu verhindern, indem Sie Anführungszeichen und andere Sonderzeichen aus den eingefügten Werten maskieren.

Umgekehrt ein PreparedStatement könnte wie folgt aufgerufen werden, indem .setXYZ() verwendet wird Methoden zum Einfügen von Werten mit automatischem Zeichen-Escape während der Methodenausführung:

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();

Vorkompilierung

Ein weiterer Vorteil eines PreparedStatement ist, dass das SQL selbst pre-compiled ist ein einziges Mal und dann vom System im Speicher behalten, anstatt jedes Mal kompiliert zu werden, wenn die Anweisung aufgerufen wird. Dies ermöglicht eine schnellere Ausführung, insbesondere wenn ein PreparedStatement wird in Verbindung mit batches verwendet , mit denen Sie eine Serie ausführen können (oder batch ) von SQL-Anweisungen gleichzeitig während einer einzigen Datenbankverbindung.

Hier haben wir zum Beispiel eine Funktion, die eine List akzeptiert von Büchern. Für jedes book in der Liste wollen wir ein INSERT ausführen -Anweisung, aber wir werden sie alle zu einem Stapel von PreparedStatements hinzufügen und sie alle auf einen Schlag ausführen:

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();
  }
}

Einfügung von anormalen Datentypen in eine SQL-Anweisung

Der letzte Vorteil von PreparedStatements Was wir behandeln werden, ist die Möglichkeit, abnormale Datentypen in die SQL-Anweisung selbst einzufügen, wie z. B. Timestamp , InputStream , und viele mehr.

Beispielsweise können wir ein PreparedStatement verwenden um ein Titelbild zu unserem Bucheintrag hinzuzufügen, indem Sie .setBinaryStream() verwenden Methode:

ps = connection.prepareStatement("INSERT INTO books (cover_photo) VALUES (?)");
ps.setBinaryStream(1, book.getPhoto());
ps.executeUpdate();