PreparedStatement
PreparedStatement
參考資料:JDBC為什麼要使用PreparedStatement而不是Statement(http://www.importnew.com/5006.html)
Java 提供了三種API來執行查詢語句
Statement - 通用查詢
PreparedStatement - 參數化查詢
CallableStatement - 存儲過程
PreparedStatement 是什麼?
import java.sql.PreparedStatement;
使用PreparedStatement,DBMS會對Query 進行預編譯處理,將語句的部分儲存起來,以後雖然輸入的參數不同,一樣可以拿出來用。這樣一來,它比Statement 的查詢速度更快。
參數化查詢
?
代表參數的位置,因為可以用不同的參數調用它。
PreparedStatement 比 Statement 更快
PreparedStatement 擁有更佳的性能優勢,SQL語句會在DBMS進行預編譯,並且將執行計畫緩存起來。後續可以用參數化查詢,而不是字串追加。
PreparedStatement 可以防止 SQL注入攻擊
在使用參數化查詢的情況下,DBMS是拿編譯完的語句加上參數去運行。 不會將參數視為SQL Query的一部分。因此就算參數含有破壞性指令,也不會被DBMS所運行。
另外一種防止 SQL注入攻擊 的方式
在組SQL Query的時候,先對使用者傳入的參數,單引號都取代為連續2個單引號,以此去避免SQL 注入。
可讀性
比起凌亂的字串追加,利用參數去提升可讀性。
PreparedStatement的局限性
儘管PreparedStatement非常實用,但是它仍有一定的限制。 1.為了防止SQL注入攻擊,PreparedStatement不允許一個佔位符(?)有多個值,在執行有IN子句查詢的時候這個問題變得棘手起來。下面這個SQL查詢使用PreparedStatement就不會返回任何結果
部分總結
PreparedStatement可以寫參數化查詢,比Statement能獲得更好的性能。
對於PreparedStatement來說,數據庫可以使用已經編譯過及定義好的執行計劃,這種預處理語句查詢比普通的查詢運行速度更快。
PreparedStatement可以阻止常見的SQL注入式攻擊。
PreparedStatement可以寫動態查詢語句
PreparedStatement與java.sql.Connection對像是關聯的,一旦你關閉了connection,PreparedStatement也沒法使用了。
“?”叫做佔位符。
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
where many column
注意:參數必須為null
才會被 coalesce()
跳過,空字串會被吃進去
Last updated