preparestatement和statement的區別&&簡單的SQL注入


在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 --


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM