sql >> Databasteknik >  >> RDS >> Database

Skillnaden mellan ett JDBC-uttalande och ett förberett uttalande

Även om det är sant att en grundläggande SQL-sats i många fall kommer att få jobbet gjort för många databasändringar eller frågor, är det ofta en bästa praxis att använda den flexibilitet och fördelar som du får genom att använda PreparedStatements .

De primära skillnaderna mellan en standard JDBC-sats och en PreparedStatement definieras bäst av fördelarna att en PreparedStatement ger dig och din ansökan. Nedan undersöker vi de tre kärnfördelarna med PreparedStatements över vanliga JDBC/SQL-satser.

SQL Injection Prevention

Den första fördelen med att använda en PreparedStatement är att du kan dra nytta av mängden .setXYZ() metoder, såsom .setString() , som gör att din kod automatiskt kan undkomma specialtecken som citattecken inom den godkända SQL-satsen, vilket förhindrar den alltid farliga SQL injection attack.

Till exempel, i en standard SQL-sats kan det vara typiskt att infoga värden direkt i satsen, som så:

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

Detta skulle tvinga dig att köra din egen kod för att förhindra SQL-injektioner genom att undvika citattecken och andra specialtecken från de infogade värdena.

Omvänt, en PreparedStatement kan anropas enligt följande med .setXYZ() metoder för att infoga värden med automatiskt tecken escape under metodkörning:

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

Förkompilering

En annan fördel med en PreparedStatement är att själva SQL är pre-compiled en enda gång och sedan bevaras i minnet av systemet, istället för att kompileras varje gång uttalandet anropas. Detta möjliggör snabbare exekvering, särskilt när en PreparedStatement används tillsammans med batches , som låter dig köra en serie (eller batch ) av SQL-satser på en gång under en enda databasanslutning.

Här har vi till exempel en funktion som accepterar en List av böcker. För varje book i listan vill vi köra en INSERT uttalande, men vi kommer att lägga till alla i en sats av PreparedStatements och avrätta dem alla i ett svep:

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

Infogande av onormala datatyper i SQL-sats

Den sista fördelen med PreparedStatements som vi kommer att täcka är möjligheten att infoga onormala datatyper i själva SQL-satsen, såsom Timestamp , InputStream , och många fler.

Till exempel kan vi använda en PreparedStatement för att lägga till ett omslagsfoto till vår bokföring med hjälp av .setBinaryStream() metod:

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

  1. Skapa ett SQL Server Agent Job med T-SQL

  2. skillnaden mellan förklara plan och genomförandeplan

  3. PDO med INSERT INTO genom upprättade utlåtanden

  4. PostgreSQL via SSH Tunnel