Verschil tussen Statement en PreparedStatement

Java Top

Ik heb zojuist het nieuwe aangekondigd Leer de lente natuurlijk, gericht op de basisprincipes van Spring 5 en Spring Boot 2:

>> BEKIJK DE CURSUS

1. Overzicht

In deze tutorial onderzoeken we de verschillen tussen JDBC's Uitspraak en PreparedStatement interfaces. We zullen het niet dekken Oproepbare verklaring, een JDBC API-interface die wordt gebruikt om opgeslagen procedures uit te voeren.

2. JDBC API-interface

Beide Uitspraak en PreparedStatement kan worden gebruikt om SQL-queries uit te voeren. Deze interfaces lijken erg op elkaar. Ze verschillen echter aanzienlijk van elkaar in functies en prestaties:

  • Uitspraak Wordt gebruikt om op string gebaseerde SQL uit te voeren vragen
  • PreparedStatement Wordt gebruikt om SQL-query's met parameters uit te voeren

Om te kunnen gebruiken Uitspraak en PreparedStatement in onze voorbeelden verklaren we de h2 JDBC-connector als afhankelijkheid in ons pom.xml het dossier:

 com.h2database h2 1.4.200 

Laten we een entiteit definiëren die we in dit artikel zullen gebruiken:

openbare klasse PersonEntity {privé int id; private String naam; // standaard setters en getters}

3. Uitspraak

Ten eerste de Uitspraak interface accepteert strings als SQL-query's. Dus, de code wordt minder leesbaar wanneer we SQL-strings samenvoegen:

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

Ten tweede, het is kwetsbaar voor SQL-injectie . De volgende voorbeelden illustreren deze zwakte.

In de eerste regel zal de update de kolom "naam"Op alle rijen tot"hacker", Aangezien alles na" - "wordt geïnterpreteerd als een opmerking in SQL en de voorwaarden van de update-instructie worden genegeerd. Op de tweede regel zal de invoeging mislukken omdat het citaat op de "naam"Kolom is niet voorzien van escapecodes:

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

Ten derde, JDBC geeft de query met inline-waarden door aan de database. Daarom is er geen optimalisatie van zoekopdrachten, en vooral: de database-engine moet voor alle controles zorgen. Ook zal de query niet hetzelfde verschijnen voor de database en het zal cachegebruik voorkomen. Evenzo moeten batchupdates afzonderlijk worden uitgevoerd:

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

Ten vierde, de Uitspraak interface is geschikt voor DDL-zoekopdrachten zoals CREATE, ALTER en DROP :

public void createTables () {String query = "maak een tabel als deze niet bestaat PERSONS (ID INT, NAAM VARCHAR (45))"; connection.createStatement (). executeUpdate (query); }

Tenslotte, de Uitspraak interface kan niet worden gebruikt voor het opslaan en ophalen van bestanden en arrays.

4. PreparedStatement

Ten eerste de PreparedStatement breidt de Uitspraak koppel. Het heeft methoden om verschillende objecttypen te binden, inclusief bestanden en arrays. Vandaar, de code wordtmakkelijk te begrijpen:

public void insert (PersonEntity personEntity) {String query = "INVOEGEN IN personen (id, naam) WAARDEN (?,?)"; PreparedStatement voorbereideStatement = connection.prepareStatement (vraag); voorbereideStatement.setInt (1, personEntity.getId ()); voorbereideStatement.setString (2, personEntity.getName ()); voorbereideStatement.executeUpdate (); }

Ten tweede, het beschermt tegen SQL-injectie, door de tekst voor alle opgegeven parameterwaarden te escapen:

@Test ongeldig whenInsertAPersonWithQuoteInText_thenItNeverThrowsAnException () {assertDoesNotThrow (() -> dao.insert (nieuwe PersonEntity (1, "O'Brien"))); } @Test void whenAHackerUpdateAPerson_thenItUpdatesTheTargetedPerson () gooit SQLException {dao.insert (Arrays.asList (nieuwe PersonEntity (1, "john"), nieuwe PersonEntity (2, "skeet"))); dao.update (nieuwe PersonEntity (1, "hacker '-")); Lijstresultaat = dao.getAll (); assertEquals (Arrays.asList (nieuwe PersonEntity (1, "hacker '-"), nieuwe PersonEntity (2, "skeet")), resultaat); }

Ten derde, de PreparedStatement maakt gebruik van pre-compilatie. Zodra de database een query ontvangt, wordt de cache gecontroleerd voordat de query wordt voorgecompileerd. Bijgevolg, als het niet in de cache is opgeslagen, zal de database-engine het opslaan voor het volgende gebruik.

Bovendien, deze functie versnelt de communicatie tussen de database en de JVM via een niet-SQL binair protocol. Dat wil zeggen dat er minder data in de pakketten zit, waardoor de communicatie tussen de servers sneller verloopt.

Ten vierde, de PreparedStatement biedt een batchuitvoering tijdens een enkele databaseverbinding. Laten we dit in actie zien:

public void insert (List personEntities) gooit SQLException {String query = "INVOEGEN IN personen (id, naam) WAARDEN (?,?)"; PreparedStatement voorbereideStatement = connection.prepareStatement (vraag); voor (PersonEntity personEntity: personEntities) {voorbereideStatement.setInt (1, personEntity.getId ()); voorbereideStatement.setString (2, personEntity.getName ()); voorbereideStatement.addBatch (); } voorbereideStatement.executeBatch (); }

Vervolgens de PreparedStatement biedt een gemakkelijke manier om bestanden op te slaan en op te halen met BLOB en CLOB gegevenstypen. Op dezelfde manier helpt het om lijsten op te slaan door te converteren java.sql.Array naar een SQL-array.

Ten slotte de PreparedStatement implementeert methoden zoals getMetadata () die informatie bevatten over het geretourneerde resultaat.

5. Conclusie

In deze tutorial hebben we de belangrijkste verschillen tussen PreparedStatement en Uitspraak. Beide interfaces bieden methoden om SQL-query's uit te voeren, maar het is geschikter om te gebruiken Uitspraak voor DDL-vragen en PreparedStatement voor DML-zoekopdrachten.

Zoals gewoonlijk zijn alle codevoorbeelden beschikbaar op GitHub.

Java onderkant

Ik heb zojuist het nieuwe aangekondigd Leer de lente natuurlijk, gericht op de basisprincipes van Spring 5 en Spring Boot 2:

>> BEKIJK DE CURSUS