日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Statement和PreparedStatement深入学习总结

發布時間:2024/4/14 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Statement和PreparedStatement深入学习总结 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

最近在看java安全編碼方面的書籍,在看到SQL注入漏洞的問題時,引發了我對Statement和PreparedStatement深入總結的欲望,廢話少說,下面咱們就正式開始。

當初始的SQL查詢被修改成另一個完全不同形式的查詢的時候,就會出現SQL注入漏洞。執行這一被修改過的查詢就可能會導致信息泄露或者數據被修改。防止SQL注入漏洞的主要方法是:凈化并驗證非受信輸入,同時采用參數化查詢的方法。

//創建數據庫連接的過程略String sql="select * from db_user where username = " + username + "and passord = " + password;Statement stmt = connect.createStatement();ResultSet rs = stmt.executeQuery(sql);

采用以上方法實現數據查詢時,如果攻擊者能夠替代username和password中的任意字符串,它們可以使用類似下面這種方式實現SQL注入:

select * from db_user where username = '隨意' and password = '' or '1' = '1';

因為’1’=’1’肯定成立,所以可以任何通過驗證.更有甚者:把[‘;drop table tb_name;]作為password傳入進來,則:

select * from db_user where username = '隨意' and password = '';drop table tb_name;

有些數據庫是不會讓你成功的,但也有很多數據庫就可以使這些語句得到執行。而如果你使用預編譯語句。你傳入的任何內容就不會和原來的語句發生任何匹配的關系。(前提是數據庫本身支持預編譯,但上前可能沒有什么服務端數據庫不支持編譯了,只有少數的桌面數據庫,就是直接文件訪問的那些)只要全使用預編譯語句,你就用不著對傳入的數據做任何過濾。而如果使用普通的statement,有可能要對drop,等做費盡心機的判斷和過濾。

改進方法:

//創建數據庫連接的過程略String sql="select * from db_user where username = ? and passord = ?";PreparedStatement stmt = connect.preparedStatement();stmt.setString(1,username);stme.setString(2,password);ResultSet rs = stmt.executeQuery(sql);

通過使用PreparedStatement類的set*()方法,可以進行強類型檢查。這樣可以減少SQL注入漏洞。

一、分情況使用Statement和PreparedStatement對象

JDBC驅動的最佳化是基于使用的是什么功能. 選擇PreparedStatement還是Statement取決于你要怎么使用它們. 對于只執行一次的SQL語句選擇Statement是最好的. 相反, 如果SQL語句被多次執行選用PreparedStatement是最好的.

PreparedStatement的第一次執行消耗是很高的. 它的性能體現在后面的重復執行. 使用PreparedStatement的方式來執行一個針對數據庫表的查詢. JDBC驅動會發送一個網絡請求到數據解析和優化這個查詢. 而執行時會產生另一個網絡請求. 在JDBC驅動中,減少網絡通訊是最終的目的. 如果我的程序在運行期間只需要一次請求, 那么就使用Statement. 對于Statement, 同一個查詢只會產生一次網絡到數據庫的通訊.

對于使用PreparedStatement池的情況下,當使用PreparedStatement池時, 如果一個查詢很特殊, 并且不太會再次執行到, 那么可以使用Statement. 如果一個查詢很少會被執行,但連接池中的Statement池可能被再次執行, 那么請使用PreparedStatement. 在不是Statement池的同樣情況下, 請使用Statement.

二、PreparedStatement的Batch功能

Update大量的數據時, 先構建一個INSERT語句再多次的執行, 會導致很多次的網絡連接.。要減少JDBC的調用次數改善性能, 可以使用PreparedStatement的AddBatch()方法一次性發送多個查詢給數據庫。

初始實現:PreparedStatement ps = conn.prepareStatement( "INSERT into db_user values (?, ?, ?)"); for (n = 0; n < 100; n++) { ps.setString(name[n]); ps.setLong(id[n]); ps.setInt(salary[n]); ps.executeUpdate(); } 改進實現://使用Batch功能 PreparedStatement ps = conn.prepareStatement( "INSERT into db_user values (?, ?, ?)"); for (n = 0; n < 100; n++) { ps.setString(username[n]); ps.setString(password[n]); ps.addBatch(); } ps.executeBatch();

在初始實現中, PreparedStatement被用來多次執行INSERT語句。 在這里,執行了100次INSERT操作, 共有101次網絡往返。 其中,1次往返是預儲statement, 另外100次往返執行每個迭代。 在改進實現中, 當在100次INSERT操作中使用addBatch()方法時, 只有兩次網絡往返。 1次往返是預儲statement, 另一次是執行batch命令。雖然Batch命令會用到更多的數據庫的CPU周期, 但是通過減少網絡往返,性能得到提高。 記住, JDBC的性能最大的增進是減少JDBC驅動與數據庫之間的網絡通訊。

注:Oracel 10G的JDBC Driver限制最大Batch size是16383條,如果addBatch超過這個限制,那么executeBatch時就會出現“無效的批值”(Invalid Batch Value) 異常。因此在如果使用的是Oracle10G,在此bug減少前,Batch size需要控制在一定的限度。

超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生

總結

以上是生活随笔為你收集整理的Statement和PreparedStatement深入学习总结的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。