更新時間:2021-02-24 17:42:11 來源:動力節(jié)點 瀏覽1353次
PreparedStatement是用來執(zhí)行SQL查詢語句的API之一,Java提供了 Statement、PreparedStatement 和 CallableStatement三種方式來執(zhí)行查詢語句,其中 Statement 用于通用查詢,PreparedStatement 用于執(zhí)行參數(shù)化查詢,而 CallableStatement則是用于存儲過程。同時PreparedStatement還經(jīng)常會在Java面試被提及,本文我們就來詳細聊一聊JDBC中的PreparedStatement。
那么PreparedStatement是什么呢?PreparedStatement是java.sql包下面的一個接口,用來執(zhí)行SQL語句查詢,通過調(diào)用connection.preparedStatement(sql)方法可以獲得PreparedStatment對象。數(shù)據(jù)庫系統(tǒng)會對SQL語句進行預編譯處理(如果JDBC驅(qū)動支持的話),預處理語句將被預先編譯好,這條預編譯的sql查詢語句能在將來的查詢中重用,這樣一來,它比Statement對象生成的查詢速度更快。下面是一個例子:
public class PreparedStmtExample {
?public static void main(String args[]) throws SQLException
?{
??????Connection conn = DriverManager.getConnection("mysql:\\localhost:1520",
??????"root","root");
??????PreparedStatement preStatement = conn.prepareStatement("select distinct ??????loan_type from loan where bank=?");
??????preStatement.setString(1, "Citibank");
??????ResultSet result = preStatement.executeQuery();
??????while(result.next())
??????{
??????????System.out.println("Loan Type: " + result.getString("loan_type"));
??????} ??????
????}}
Output:
Loan Type: Personal Loan
Loan Type: Auto Loan
Loan Type: Home Loan
Loan Type: Gold Loan
這個例子中,如果還是用 PreparedStatement 做同樣的查詢,哪怕參數(shù)值不一樣,比如:”Standard Chated” 或者”HSBC”作為參數(shù)值,數(shù)據(jù)庫系統(tǒng)還是會去調(diào)用之前編譯器編譯好的執(zhí)行語句(系統(tǒng)庫系統(tǒng)初次會對查詢語句做最大的性能優(yōu)化)。默認會返回”TYPE_FORWARD_ONLY”類型的結(jié)果集( ResultSet ),當然你也可以使用preparedstatment()的重載方法返回不同類型的結(jié)果集。
使用 PreparedStatement 最重要的一點好處是它擁有更佳的性能優(yōu)勢,SQL語句會預編譯在數(shù)據(jù)庫系統(tǒng)中。執(zhí)行計劃同樣會被緩存起來,它允許數(shù)據(jù)庫做參數(shù)化查詢。使用預處理語句比普通的查詢更快,因為它做的工作更少(數(shù)據(jù)庫對SQL語句的分析,編譯,優(yōu)化已經(jīng)在第一次查詢前完成了)。為了減少數(shù)據(jù)庫的負載,生產(chǎn)環(huán)境中德JDBC代碼你應(yīng)該總是使用PreparedStatement 。值得注意的一點是:為了獲得性能上的優(yōu)勢,應(yīng)該使用參數(shù)化sql查詢而不是字符串追加的方式。
比起凌亂的字符串追加似的查詢,PreparedStatement查詢可讀性更好、更安全。
PreparedStatement的局限性
盡管PreparedStatement非常實用,但是它仍有一定的限制。了防止SQL注入攻擊,PreparedStatement不允許一個占位符(?)有多個值,在執(zhí)行有**IN**子句查詢的時候這個問題變得棘手起來。
關(guān)于PreparedStatement接口,需要重點記住的是:
1. PreparedStatement可以寫參數(shù)化查詢,比Statement能獲得更好的性能。
2. 對于PreparedStatement來說,數(shù)據(jù)庫可以使用已經(jīng)編譯過及定義好的執(zhí)行計劃,這種預處理語句查詢比普通的查詢運行速度更快。
3. PreparedStatement可以阻止常見的SQL注入式攻擊。
4. PreparedStatement可以寫動態(tài)查詢語句
5. PreparedStatement與java.sql.Connection對象是關(guān)聯(lián)的,一旦你關(guān)閉了connection,PreparedStatement也沒法使用了。
6. “?” 叫做占位符。
7. PreparedStatement查詢默認返回FORWARD_ONLY的ResultSet,你只能往一個方向移動結(jié)果集的游標。當然你還可以設(shè)定為其他類型的值如:”CONCUR_READ_ONLY”。
8. 不支持預編譯SQL查詢的JDBC驅(qū)動,在調(diào)用connection.prepareStatement(sql)的時候,它不會把SQL查詢語句發(fā)送給數(shù)據(jù)庫做預處理,而是等到執(zhí)行查詢動作的時候(調(diào)用executeQuery()方法時)才把查詢語句發(fā)送個數(shù)據(jù)庫,這種情況和使用Statement是一樣的。
9. 占位符的索引位置從1開始而不是0,如果填入0會導致*java.sql.SQLException invalid column index*異常。所以如果PreparedStatement有兩個占位符,那么第一個參數(shù)的索引時1,第二個參數(shù)的索引是2.
以上就是關(guān)于JDBC中的PreparedStatement的詳細介紹,當然由于篇幅限制我們沒有給出實際的代碼示例,在本站的JDBC教程中有很多很好的代碼實例,想要探究學習的小伙伴可以去下載學習,提高自己對JDBC的實際應(yīng)用能力。