sql >> Database >  >> RDS >> Database

Het verschil tussen een JDBC-verklaring en een voorbereide verklaring

Hoewel het waar is dat in veel gevallen een eenvoudige SQL-instructie de klus zal klaren voor veel databasewijzigingen of query's, is het vaak een best practice om gebruik te maken van de flexibiliteit en voordelen die u worden geboden door gebruik te maken van PreparedStatements .

De belangrijkste verschillen tussen een standaard JDBC-statement en een PreparedStatement worden het best gedefinieerd door de voordelen dat een PreparedStatement biedt u en uw toepassing. Hieronder onderzoeken we de drie belangrijkste voordelen van PreparedStatements over reguliere JDBC/SQL-statements.

SQL-injectiepreventie

Het eerste voordeel van het gebruik van een PreparedStatement is dat u kunt profiteren van de veelheid aan .setXYZ() methoden, zoals .setString() , waarmee uw code automatisch kan ontsnappen aan speciale tekens zoals aanhalingstekens binnen de doorgegeven SQL-instructie, waardoor de altijd gevaarlijke SQL injection wordt voorkomen aanval.

In een standaard SQL-statement kan het bijvoorbeeld gebruikelijk zijn om waarden direct inline met het statement in te voegen, zoals:

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

Dit zou u dwingen uw eigen code uit te voeren om SQL-injecties te voorkomen door aanhalingstekens en andere speciale tekens uit de ingevoegde waarden te laten ontsnappen.

Omgekeerd, een PreparedStatement kan als volgt worden aangeroepen, met behulp van de .setXYZ() methoden om waarden in te voegen met automatische escapetekens tijdens de uitvoering van de methode:

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

Pre-compilatie

Nog een voordeel van een PreparedStatement is dat de SQL zelf pre-compiled . is een enkele keer en vervolgens door het systeem in het geheugen bewaard, in plaats van elke keer dat de instructie wordt aangeroepen, te worden gecompileerd. Dit zorgt voor een snellere uitvoering, vooral wanneer een PreparedStatement wordt gebruikt in combinatie met batches , waarmee u een reeks . kunt uitvoeren (of batch ) van SQL-instructies tegelijk tijdens een enkele databaseverbinding.

Hier hebben we bijvoorbeeld een functie die een List . accepteert van boeken. Voor elk book in de lijst willen we een INSERT . uitvoeren statement, maar we gaan ze allemaal toevoegen aan een batch van PreparedStatements en voer ze allemaal in één klap uit:

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

Invoeging van abnormale gegevenstypen in SQL-instructie

Het laatste voordeel van PreparedStatements die we zullen behandelen, is de mogelijkheid om abnormale gegevenstypen in de SQL-instructie zelf in te voegen, zoals Timestamp , InputStream , en nog veel meer.

We kunnen bijvoorbeeld een PreparedStatement . gebruiken om een ​​omslagfoto toe te voegen aan ons boekverslag met behulp van de .setBinaryStream() methode:

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

  1. Hoe kan ik gegevens uit een versleutelde database lezen met SQLiteAssetHelper?

  2. SQL Server PIVOT misschien?

  3. Rijdoelen, deel 3:Anti-joins

  4. Hoe de uitvoer van DBMS_OUTPUT.PUT_LINE omleiden naar een bestand?