1. 程式人生 > 實用技巧 >JDBC之PreparedStatement 詳解

JDBC之PreparedStatement 詳解

簡介

PreparedStatement 是一個特殊的Statement物件,如果我們只是來查詢或者更新資料的話,最好用PreparedStatement代替Statement,因為它有以下有點:

  1. 簡化Statement中的操作
  2. 提高執行語句的效能
  3. 可讀性和可維護性更好
  4. 安全性更好。
  5. 使用PreparedStatement能夠預防SQL注入攻擊,所謂SQL注入,指的是通過把SQL命令插入到Web表單提交或者輸入域名或者頁面請求的查詢字串,最終達到欺騙伺服器,達到執行惡意SQL命令的目的。注入只對SQL語句的編譯過程有破壞作用,而執行階段只是把輸入串作為資料處理,不再需要對SQL語句進行解析,因此也就避免了類似select * from user where name='aa' and password='bb' or 1=1的sql注入問題的發生。

Statement 和 PreparedStatement之間的關係和區別.

  • 關係:PreparedStatement繼承自Statement,都是介面
  • 區別:PreparedStatement可以使用佔位符,是預編譯的,批處理比Statement效率高

入門使用

建立PreparedStatement

建立一個PreparedStatement PreparedStatement物件的建立也同樣離不開 DriverManger.getConnect()物件,因為它也是建立在連線到資料庫之上的操作。

      /** 1. init PreparedStatement*/
        Class.forName("com.mysql.jdbc.Driver");
        String url = "jdbc:mysql://localhost:3306/db_test?useSSL=false";
        String username = "root";
        String password = "root";
        Connection connection = DriverManager.getConnection(url, username, password);
        String sql = "update user set username=? where id = ?";
        PreparedStatement preparedStatement = connection.prepareStatement(sql);

設定入參

往PreparedStatement裡寫入引數

看上面那個sql 字串,中間有幾個?,它在這裡有點佔位符的意思,然後我們可以通過PreparedStatement的setString(),等方法來給佔位符進行賦值,使得sql語句變得靈活。

        /** 2. prepare param*/
        preparedStatement.setString(1, "feifz");
        preparedStatement.setInt(2, 2);

引數中的第一個引數分別是1和2,它代表的是第幾個問號的位置。如果sql語句中只有一個問號,那就不用宣告這個引數。

執行更新

 /** 3. execute update*/
  int result = preparedStatement.executeUpdate();
  System.out.printf("更新記錄數:"+result+"\n");

結果:

更新記錄數:1

執行查詢

如果是執行查詢資料庫的話,也像Statement物件執行excuteQuery()一樣返回一個ResultSet結果集。

/** 4. execute select*/
String sql2 = "select * from user";
        ResultSet resultSet = preparedStatement.executeQuery(sql2);
        while (resultSet.next()) {
            int id = resultSet.getInt("id");
            String username = resultSet.getString("username");
            String dept = resultSet.getString("dept");
            System.out.println("id:"+id +"username->"+ username + ",dept-> " + dept );
        }

執行結果:

id:1username->Fant.J,dept-> 測試部
id:2username->feifz,dept-> 研發部
id:3username->xixi,dept-> 產品部
id:4username->hah,dept-> 整合部
id:5username->zeze,dept-> 研發部

完整程式碼

package com.github.feifuzeng.middleware.mybatis.jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

/**
 * @author feifz
 * @version 1.0.0
 * @Description PreparedStatement簡單demo
 * @createTime 2019年08月29日 20:21:00
 */
public class PrepareStatementSimpleDemo {

    public static void main(String[] args) throws Exception {

        /** 1. init PreparedStatement*/
        Class.forName("com.mysql.jdbc.Driver");
        String url = "jdbc:mysql://localhost:3306/db_test?useSSL=false";
        String user = "root";
        String password = "root";
        Connection connection = DriverManager.getConnection(url, user, password);
        String sql = "update user set username=? where id = ?";
        PreparedStatement preparedStatement = connection.prepareStatement(sql);

        /** 2. prepare param*/
        preparedStatement.setString(1, "feifz");
        preparedStatement.setInt(2, 2);

        /** 3. execute update*/
        int result = preparedStatement.executeUpdate();
        System.out.printf("更新記錄數:"+result+"\n");

        /** 4. execute select*/

        String sql2 = "select * from user";
        ResultSet resultSet = preparedStatement.executeQuery(sql2);
        while (resultSet.next()) {
            int id = resultSet.getInt("id");
            String username = resultSet.getString("username");
            String dept = resultSet.getString("dept");
            System.out.println("id:"+id +"username->"+ username + ",dept-> " + dept );
        }


    }
}

參考

  1. https://juejin.im/post/5abb78c8f265da23994e9643

結語

歡迎關注微信公眾號『碼仔zonE』,專注於分享Java、雲端計算相關內容,包括SpringBoot、SpringCloud、微服務、Docker、Kubernetes、Python等領域相關技術乾貨,期待與您相遇!