Brian的雜記
  • Introduction
  • Brian's 雜記
    • My Awesome API
    • FB 大頭貼
    • 硬體雜記
    • PHP
    • project
      • 模擬器
      • WAMP
    • WinMerge
    • 雜記
      • LINQ
      • 方法
      • Grid View
      • namespace
      • global
      • 物件導向
      • Excel
      • VS2017
      • single sign on
      • Master
      • Https
      • 憑證
      • 略過憑證不符
      • NLog
      • 團隊開發
      • .NET Core
      • 共用網路上的芳鄰
      • 爬蟲
      • NPOI
      • RSS
      • 多執行緒
      • 記憶體回收
      • 密碼學
        • BCrypt
        • AES
      • 主機環境建置
      • Session
      • Error
      • IIS 相關
      • 無障礙相關
      • 介面
        • 影像地圖
      • telnet
        • smtp
      • nslookup
      • 協助客戶解決問題
      • 驗證欄位
      • 網站管理
      • 工具整理
    • 正規表示法
    • 影像處理
    • IntelliJ Idea
    • 觀念
      • Clean Code
        • 命名
        • 函式
        • 註解
        • 編排
        • 物件及資料結構
        • 錯誤處理
        • 邊界
        • 單元測試
        • 類別
      • Java 程式風格
      • Design Pattern
        • 單例模式
      • 同步
      • 畫圖
        • ER-Model
        • 類別圖
        • Use Case
        • 有限狀態機
      • 資料 API 文件 分析
      • CORS & SSL
      • 利用DISC幫助溝通
      • OAS
    • 檔案上傳
      • FileStore
      • App Engine
      • Google Storage
    • OAuth vs Open ID
    • MIME
    • 虛擬桌面
    • 待看資料
    • Selenium
    • CDN
    • HTTP
    • 編碼
    • 2nd-ML100Days
      • jupyter
    • 微服務
      • 設計
        • 1 ~ 5
        • 6
        • 7
        • 8
        • 9
    • Gradle
    • Maven
    • Error
    • 批次檔 BAT
    • Kurento
    • WebSocket & WebRTC
  • 需求面能力
    • User Story
  • Google Cloud Platform
    • Compute Engine
  • Python
    • 基本語法
    • Pandas
    • 套件
    • Matplotlib
    • Encoder
    • jupyter
  • Java
    • Java
      • File
      • Exception
      • 物件導向觀念
      • 加密
      • HTTP
      • 集合
      • Stream()
      • Web
      • ResultSet
      • JDK6
      • JDK8
    • 讀取、複寫MP3 Tag
    • Log4j2
    • Servlet
      • 容器
    • JSP
    • JBOSS
    • JWT
    • PreparedStatement
    • Error
    • Spring
      • Spring Boot
        • @Value
        • Build
      • RequestParameter
      • Error
      • Autowired
      • JPA
      • FeignClient
      • WebSocket
      • thymeleaf
      • Security
      • Test
      • Scheduled
      • Redirect
    • IntelliJ
  • Linux
    • Linux
    • Shell Script
    • Cygwin(在Windows執行Linux指令)
  • 前端
    • HTML
      • Link
    • CSS
      • Position
      • padding color
      • display
    • JS
      • jQuery
        • Select2
      • fancybox
      • ES6
      • 效能
      • GoogleMap API
        • Marker
        • InfoWindow
      • 事件
      • CKEditor
      • TGOS
      • JSON
      • QRcode
      • 核心概念
        • 物件 變數 型別
          • number
          • String
          • boolean
          • null & undefined
          • Symbol
        • JS 物件概念
        • 深入理解JS 函式物件
        • 更多ES2015/ES6 全新語言特性
      • Promise
    • 效果應用
  • 資料庫
    • 注意事項
    • MariaDB
    • MySQL
      • inner join 和 join
      • 字串比對
      • 倒數資料
    • SQL
      • DDL 資料定義語言
      • DML 資料操縱語言
      • DCL 資料控制語言
      • TCL 交易控制語言
      • T-SQL
      • CTE
      • JOIN
    • Oracle
    • MSSQL 操作
      • 新增使用者
      • SQL 指令
      • Sequence
    • 差異比較
    • MyBatis
    • Workbench 操作
    • SQL Injection
  • 版本控制
    • Gitlab
      • sign up
      • sign in
      • add project
      • add members
    • SourceGit
      • install
    • SmartGit
      • install
      • operate
      • git 操作雜記
    • TortoiseGit
    • Git
    • TFS
    • SVN
  • Test
    • 軟體測試原則
    • 演算法
    • XMind
      • install
    • Jenkins
      • 建置
    • HTTPie
    • Postman
    • 測試驅動開發
    • 撰寫測試的觀念
    • 測試框架
    • IoC & DI
    • 隔絕相依性的方式
    • JUnit
    • NUnit
    • 習慣
    • 虛設常式
  • Angular
    • hello world
    • ng-options
    • ES6
    • Build & Conponect
    • HttpClient
    • 部署
  • ASP.NET Web Form
    • Chapter 2
      • 2-1
        • 小東西
    • 略過請求驗證
  • Go
Powered by GitBook
On this page
  • PreparedStatement
  • PreparedStatement 是什麼?
  • 參數化查詢
  • PreparedStatement 比 Statement 更快
  • PreparedStatement 可以防止 SQL注入攻擊
  • 可讀性
  • PreparedStatement的局限性
  • 部分總結
  • JDBC
  • NamedParameterJdbcTemplate 的 範例
  • where .. in
  • where many column

Was this helpful?

  1. Java

PreparedStatement

PreviousJWTNextError

Last updated 4 years ago

Was this helpful?

PreparedStatement

參考資料:JDBC為什麼要使用PreparedStatement而不是Statement()

Java 提供了三種API來執行查詢語句

Statement - 通用查詢

PreparedStatement - 參數化查詢

CallableStatement - 存儲過程

PreparedStatement 是什麼?

import java.sql.PreparedStatement;

使用PreparedStatement,DBMS會對Query 進行預編譯處理,將語句的部分儲存起來,以後雖然輸入的參數不同,一樣可以拿出來用。這樣一來,它比Statement 的查詢速度更快。

參數化查詢

SELECT * from table where field = ?

?代表參數的位置,因為可以用不同的參數調用它。

PreparedStatement 比 Statement 更快

PreparedStatement 擁有更佳的性能優勢,SQL語句會在DBMS進行預編譯,並且將執行計畫緩存起來。後續可以用參數化查詢,而不是字串追加。

(X)
String loanType = getLoanType();
PreparedStatement prestmt = conn.prepareStatement("select banks from loan where loan_type=" + loanType);

(O)
PreparedStatement prestmt = conn.prepareStatement("select banks from loan where loan_type=?");
prestmt.setString(1,loanType);

PreparedStatement 可以防止 SQL注入攻擊

在使用參數化查詢的情況下,DBMS是拿編譯完的語句加上參數去運行。 不會將參數視為SQL Query的一部分。因此就算參數含有破壞性指令,也不會被DBMS所運行。

另外一種防止 SQL注入攻擊 的方式

在組SQL Query的時候,先對使用者傳入的參數,單引號都取代為連續2個單引號,以此去避免SQL 注入。

可讀性

比起凌亂的字串追加,利用參數去提升可讀性。

PreparedStatement的局限性

儘管PreparedStatement非常實用,但是它仍有一定的限制。 1.為了防止SQL注入攻擊,PreparedStatement不允許一個佔位符(?)有多個值,在執行有IN子句查詢的時候這個問題變得棘手起來。下面這個SQL查詢使用PreparedStatement就不會返回任何結果

SELECT * FROM loan WHERE loan_type IN (?)
preparedSatement.setString(1, "'personal loan', 'home loan', 'gold loan'");

部分總結

  1. PreparedStatement可以寫參數化查詢,比Statement能獲得更好的性能。

  2. 對於PreparedStatement來說,數據庫可以使用已經編譯過及定義好的執行計劃,這種預處理語句查詢比普通的查詢運行速度更快。

  3. PreparedStatement可以阻止常見的SQL注入式攻擊。

  4. PreparedStatement可以寫動態查詢語句

  5. PreparedStatement與java.sql.Connection對像是關聯的,一旦你關閉了connection,PreparedStatement也沒法使用了。

  6. “?”叫做佔位符。

  7. PreparedStatement查詢默認返回FORWARD_ONLY的ResultSet,你只能往一個方向移動結果集的游標。當然你還可以設定為其他類型的值如:”CONCUR_READ_ONLY”。

    8.不支持預編譯SQL查詢的JDBC驅動,在調用connection.prepareStatement(sql)的時候,它不會把SQL查詢語句發送給數據庫做預處理,而是等到執行查詢動作的時候(調用executeQuery()方法時)才把查詢語句發送個數據庫,這種情況和使用Statement是一樣的。

    9.佔位符的索引位置從1開始而不是0,如果填入0會導致java.sql.SQLException invalid column index異常。所以如果PreparedStatement有兩個佔位符,那麼第一個參數的索引時1,第二個參數的索引是2。

JDBC

目前有提供下列這兩種 Template JdbcTemplate NamedParameterJdbcTemplate 這兩者都是使用 PreparedStatement 去執行查詢,這些都是防止 SQL Injection的措施,在SQLInjection的處理上沒有區別。

NamedParameterJdbcTemplate 的 範例

where .. in

public List<SmsDto> selectDataBySmsId(String... smsId) {
    String sql = " SELECT * FROM " + SmsDto.TABLE_NAME +
            " WHERE sms_id in (:sms_id) ";
    
    //不吃Array,要先轉換成List
    List<String> list = new ArrayList<>(Arrays.asList(smsId));

    MapSqlParameterSource in = new MapSqlParameterSource();
    in.addValue("sms_id", list);

    return this.getNamedParameterJdbcTemplate().query(sql, in, new BeanPropertyRowMapper<>(SmsDto.class));
}

where many column

public List<SmsDto> test1(String smsId,String smsName) {
    String sql = " SELECT * FROM " + SmsDto.TABLE_NAME +
            " WHERE coalesce(:sms_id, sms_id) = sms_id " +
            " and coalesce(:sms_name, sms_name) = sms_name ";

    MapSqlParameterSource in = new MapSqlParameterSource();
    in.addValue("sms_id", smsId);
    in.addValue("sms_name", smsName);

    return this.getNamedParameterJdbcTemplate().query(sql, in, new BeanPropertyRowMapper<>(SmsDto.class));
}

注意:參數必須為null才會被 coalesce() 跳過,空字串會被吃進去

參考資料:()

http://www.importnew.com/5006.html
https://stackoverflow.com/questions/4164949/how-to-protect-against-sql-injection-when-the-where-clause-is-built-dynamically