Razlika između Izjave i Pripremljene Izjave

Java Top

Upravo sam najavio novo Uči proljeće tečaj, usredotočen na osnove Spring 5 i Spring Boot 2:

>> PROVJERITE TEČAJ

1. Pregled

U ovom uputstvu istražit ćemo razlike između JDBC-ova Izjava i PreparedStatement sučelja. Nećemo pokrivati CallableStatement, JDBC API sučelje koje se koristi za izvršavanje pohranjenih procedura.

2. JDBC API sučelje

Oba Izjava i PreparedStatement može se koristiti za izvršavanje SQL upita. Ova sučelja izgledaju vrlo slično. Međutim, međusobno se značajno razlikuju po značajkama i performansama:

  • Izjava Koristi se za izvršavanje SQL-a temeljenog na nizu upiti
  • PreparedStatement Koristi se za izvršavanje parametriziranih SQL upita

Da bi mogao koristiti Izjava i PreparedStatement u našim ćemo primjerima proglasiti h2 JDBC konektor kao ovisnost u našem pom.xml datoteka:

 com.h2data baza podataka h2 1.4.200 

Definirajmo entitet koji ćemo koristiti u ovom članku:

javna klasa PersonEntity {private int id; privatni naziv niza; // standardni postavljači i dobivači}

3. Izjava

Prvo, Izjava sučelje prihvaća nizove kao SQL upite. Tako, kod postaje manje čitljiv kada spajamo SQL nizove:

javni void insert (PersonEntity personEntity) {String query = "INSERT INTO person (id, name) VALUES (" + personEntity.getId () + ", '" + personEntity.getName () + "')"; Izjava o izjavi = connection.createStatement (); statement.executeUpdate (upit); }

Drugo, ranjiv je na ubrizgavanje SQL-a . Sljedeći primjeri ilustriraju ovu slabost.

U prvom će retku ažuriranje postaviti stupac “Ime"Na svim redovima do"haker“, Kao i bilo što nakon“ - ”tumači se kao komentar u SQL-u, a uvjeti izjave o ažuriranju bit će zanemareni. U drugom retku umetanje neće uspjeti jer navodnik na "ImeStupac nije prebjegnut:

dao.update (novi PersonEntity (1, "haker '-")); dao.insert (novi PersonEntity (1, "O'Brien"))

Treće, JDBC prosljeđuje upit s ugrađenim vrijednostima u bazu podataka. Stoga nema optimizacije upita, i što je najvažnije, mehanizam baze podataka mora osigurati sve provjere. Također, upit se neće prikazati kao isti za bazu podataka i spriječit će upotrebu predmemorije. Slično tome, batch ažuriranja treba izvršiti odvojeno:

javni void insert (Popis personEntities) {for (PersonEntity personEntity: personEntities) {insert (personEntity); }}

Četvrto, the Izjava sučelje je pogodno za DDL upite poput CREATE, ALTER i DROP :

public void createTables () {String query = "izradi tablicu ako ne postoji OSOBE (ID INT, IME VARCHAR (45))"; connection.createStatement (). executeUpdate (upit); }

Konačno, the Izjava sučelje se ne može koristiti za spremanje i dohvaćanje datoteka i nizova.

4. PreparedStatement

Prvo, PreparedStatement proširuje Izjava sučelje. Ima metode za povezivanje različitih vrsta objekata, uključujući datoteke i nizove. Stoga, kod postajelako za razumjeti:

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

Drugo, štiti od ubrizgavanja SQL-a, izbjegavanjem teksta za sve navedene vrijednosti parametara:

@Test void whenInsertAPersonWithQuoteInText_thenItNeverThrowsAnException () {assertDoesNotThrow (() -> dao.insert (novi PersonEntity (1, "O'Brien"))); } @Test void whenAHackerUpdateAPerson_thenItUpdatesTheTarrigePerson () baca SQLException {dao.insert (Arrays.asList (new PersonEntity (1, "john"), new PersonEntity (2, "skeet"))); dao.update (novi PersonEntity (1, "haker '-")); Rezultat popisa = dao.getAll (); assertEquals (Arrays.asList (novi PersonEntity (1, "haker '-"), novi PersonEntity (2, "skeet")), rezultat); }

Treće, PreparedStatement koristi predkompilaciju. Čim baza podataka dobije upit, provjerit će predmemoriju prije prethodnog sastavljanja upita. Slijedom toga, ako nije predmemorirano, mehanizam baze podataka spremit će ga za sljedeću upotrebu.

Štoviše, ova značajka ubrzava komunikaciju između baze podataka i JVM-a putem binarnog protokola koji nije SQL. Odnosno, u paketima je manje podataka, pa komunikacija između poslužitelja ide brže.

Četvrto, PreparedStatement omogućuje serijsko izvršavanje tijekom jedne veze s bazom podataka. Pogledajmo ovo na djelu:

javni void insert (Popis personEntities) baca SQLException {String query = "INSERT INTO persons (id, name) VALUES (?,?)"; PreparedStatement pripremljenStatement = connection.prepareStatement (upit); za (PersonEntity personEntity: personEntities) {PrepaStatement.setInt (1, personEntity.getId ()); PreparedStatement.setString (2, personEntity.getName ()); PreparedStatement.addBatch (); } pripremljenStament.executeBatch (); }

Dalje, PreparedStatement pruža jednostavan način za pohranu i preuzimanje datoteka pomoću BLOB i KLOB vrste podataka. U istom smislu pomaže spremanje popisa pretvaranjem java.sql.Array u SQL niz.

Na kraju, PreparedStatement provodi metode poput getMetadata () koji sadrže informacije o vraćenom rezultatu.

5. Zaključak

U ovom uputstvu predstavili smo glavne razlike između PreparedStatement i Izjava. Oba sučelja nude metode za izvršavanje SQL upita, ali je prikladnije za upotrebu Izjava za DDL upite i PreparedStatement za DML upite.

Kao i obično, svi primjeri koda dostupni su na GitHubu.

Dno Java

Upravo sam najavio novo Uči proljeće tečaj, usredotočen na osnove Spring 5 i Spring Boot 2:

>> PROVJERITE TEČAJ