在JDBC應用中,強烈建議使用PreparedStatement代替Statement.也就是說,在任何時候都不要使用Statement.
原因如下:
一.代碼的可讀性和可維護性.
var1 = "kia"; var2 = "10086" statment需要動態拼接SQL語句 statment.executeUpdate("insert sysuser (uname,uphone) values ('\"+var1+\"','\"+var2+\"')"); perparedstatment需要使用 ? 占位符 perparedstatment=conn.prepareStatement("insert sysuser (uname,uphone) values (?,?) "); perparedstatment.setString(1,var1); perparedstatment.setString(2,var2); perstmt.executeUpdate();
PreparedStatement需要編譯后的執行時再傳入參數 ==> Preparing: insert sysuser (uname,uphone) values (?,?) ==> Parameters: kia(String), 10086(String) Statement需要編譯時直接傳入參數 ==> Preparing: insert sysuser (uname,uphone) values ('kia','10086') ==> Parameters:
雖然用PreparedStatement來代替Statement會使代碼多出幾行,但這樣的代碼無論從可讀性還是可維護性上來說.都比直接用Statement的代碼高
二.PreparedStatement盡最大可能提高性能.
每一種數據庫都會盡最大努力對預編譯語句提供最大的性能優化.因為預編譯語句有可能被重復調用.所以語句在被JDBC的編譯器編譯后的執行代碼被緩存下來,那么下次調用時只要是相同的預編譯語句就不需要編譯,只要將參數直接傳入編譯過的語句執行代碼中(相當於一個涵數)就會得到執行.這並不是說只有一個Connection中多次執行的預編譯語句被緩存,而是對於整個JDBC中,只要預編譯的語句語法和緩存中匹配.那么在任何時候就可以不需要再次編譯而可以直接執行.
而statement的語句中,即使是相同一操作,而由於每次操作的數據不同所以使整個語句相匹配的機會極小,幾乎不太可能匹配.比如:
insertintotb_name(col1,col2)values('11','22');
insertintotb_name(col1,col2)values('11','23');
即使是相同操作但因為數據內容不一樣,所以整個個語句本身不能匹配,沒有緩存語句的意義.事實是沒有數據庫會對普通語句編譯后的執行代碼緩存.
當然並不是所有預編譯語句都一定會被緩存,數據庫本身會用一種策略,比如使用頻度等因素來決定什么時候不再緩存已有的預編譯結果.以保存有更多的空間存儲新的預編譯語句.
每一種數據庫都會盡最大努力對預編譯語句提供最大的性能優化.因為預編譯語句有可能被重復調用.所以語句在被DB的編譯器編譯后的執行代碼被緩存下來,那么下次調用時只要是相同的預編譯語句就不需要編譯,只要將參數直接傳入編譯過的語句執行代碼中(相當於一個涵數)就會得到執行.這並不是說只有一個Connection中多次執行的預編譯語句被緩存,而是對於整個DB中,只要預編譯的語句語法和緩存中匹配.那么在任何時候就可以不需要再次編譯而可以直接執行.而statement的語句中,即使是相同一操作,而由於每次操作的數據不同所以使整個語句相匹配的機會極小,幾乎不太可能匹配.比如:
insertintotb_name(col1,col2)values('11','22');
insertintotb_name(col1,col2)values('11','23');
即使是相同操作但因為數據內容不一樣,所以整個個語句本身不能匹配,沒有緩存語句的意義.事實是沒有數據庫會對普通語句編譯后的執行代碼緩存.
當然並不是所有預編譯語句都一定會被緩存,數據庫本身會用一種策略,比如使用頻度等因素來決定什么時候不再緩存已有的預編譯結果.以保存有更多的空間存儲新的預編譯語句.
三.最重要的一點是極大地提高了安全性.可以預防SQL注入
SQL中單行注釋 : --
例如:
正常的delete語句 :delete from sysuser WHERE uid = '2'
惡意delete語句 : delete from sysuser WHERE uid = ' 前端傳入的值 '
前端傳入的值為:2 ' OR 1 = 1 -- ;此時的SQL語句為 delete from sysuser WHERE uid = ' 2 ' OR 1 = 1 -- '
由於--單行注釋的存在,-- ' 被注釋掉了;真正執行的SQL語句為 delete from sysuser WHERE uid = ' 2 ' OR 1 = 1,會將所有的數據庫表中的數據全部刪除
而使用預編譯語句,最多最后寫入數據庫的值變為 2 ' OR 1 = 1 --