您現在的位置是:首頁 >每日動態 > 2022-09-03 17:42:16 來源:
preparedstatement批量執行
大家好,小霞來為大家解答以上的問題。preparedstatement批量執行這個很多人還不知道,現在讓我們一起來看看吧!
1、jdbc(java database connectivity,java數據庫連接)的api中的主要的四個類之一的java.sql.statement要求開發者付出大量的時間和精力。
2、在使用statement獲取jdbc訪問時所具有的一個共通的問題是輸入適當格式的日期和時間戳:2002-02-05 20:56 或者 02/05/02 8:56 pm。
3、 通過使用java.sql.preparedstatement,這個問題可以自動解決。
4、一個preparedstatement是從java.sql.connection對象和所提供的sql字符串得到的,sql字符串中包含問號(?),這些問號標明變量的位置,然后提供變量的值,最后執行語句,例如: stringsql = "select * from people p where p.id = ? and p.name = ?"; preparedstatement ps = connection.preparestatement(sql); ps.setint(1,id); ps.setstring(2,name); resultset rs = ps.executequery(); 使用preparedstatement的另一個優點是字符串不是動態創建的。
5、下面是一個動態創建字符串的例子: stringsql = "select * from people p where p.i = "+id; 這允許jvm(javavirtual machine,java虛擬機)和驅動/數據庫緩存語句和字符串并提高性能。
6、preparedstatement也提供數據庫無關性。
7、當顯示聲明的sql越少,那么潛在的sql語句的數據庫依賴性就越小。
8、由于preparedstatement具備很多優點,開發者可能通常都使用它,只有在完全是因為性能原因或者是在一行sql語句中沒有變量的時候才使用通常的statement。
9、一個完整的preparedstatement的例子: package jstarproject; import java.sql.*; public class mypreparedstatement { private final string db_driver="com.microsoft.jdbc.sqlserver.sqlserverdriver"; private final string url = "jdbc:microsoft:sqlserver://127.0.0.1:1433;databasename=pubs"; public mypreparedstatement() { } public void query() throws sqlexception{ connection conn = this.getconnection(); string strsql = "select emp_id from employee where emp_id = ?"; preparedstatement pstmt = conn.preparestatement(strsql); pstmt.setstring(1,"pma42628m"); resultset rs = pstmt.executequery(); while(rs.next()){ string fname = rs.getstring("emp_id"); system.out.println("the fname is " + fname); } rs.close(); pstmt.close(); conn.close(); } private connection getconnection() throws sqlexception{ // class. connection conn = null; try { class.forname(db_driver); conn = drivermanager.getconnection(url,"sa","sa"); } catch (classnotfoundexception ex) {} return conn; } //main public static void main(string[] args) throws sqlexception { mypreparedstatement jdbctest1 = new mypreparedstatement(); jdbctest1.query(); } } 為什么要始終使用PreparedStatement代替Statement?為什么要始終使用PreparedStatement代替Statement? 在JDBC應用中,如果你已經是稍有水平開發者,你就應該始終以PreparedStatement代替Statement.也就是說,在任何時候都不要使用Statement. 基于以下的原因: 一.代碼的可讀性和可維護性. 雖然用PreparedStatement來代替Statement會使代碼多出幾行,但這樣的代碼無論從可讀性還是可維護性上來說.都比直接用Statement的代碼高很多檔次: stmt.executeUpdate("insert into tb_name (col1,col2,col2,col4) values (+var1+,+var2+,"+var3+",+var4+)"); perstmt = con.prepareStatement("insert into tb_name (col1,col2,col2,col4) values (?,?,?,?)"); perstmt.setString(1,var1); perstmt.setString(2,var2); perstmt.setString(3,var3); perstmt.setString(4,var4); perstmt.executeUpdate(); 不用我多說,對于第一種方法.別說其他人去讀你的代碼,就是你自己過一段時間再去讀,都會覺得傷心. 為什么 PreparedStatement 很重要, 以及怎樣"正確"使用他們. 數據庫有一個艱苦的工作. 它們不斷地從許多客戶端讀取 SQL 查詢, 對數據進行盡可能高效的 查詢. 處理語句可能成為一個代價較高的操作, 但是現在數據庫都是很好的設計, 這樣這個困難 被減到最小. 但是這些優化需要應用程序開發者的協助, 這篇文章給你展示一下怎樣正確使用 PreparedStatement 來漂亮地幫助數據庫執行這些優化. 一個數據庫怎樣執行一條語句? 顯然, 不要希望這里有許多細節; 我們只看一下對這篇文章比較重要的部分. 當一個 數據庫接收 到一條語句的時候, 數據庫引擎首先解析這條語句, 查看語法錯誤. 一 旦語句解析了, 數據庫 需要找出最有效的方法來執行這條語句. 這個計算起來代價很大. 數據庫檢查什么索引(如果有 的話)能有所幫助, 或者它是否能全部讀出一張表中所有的記錄. 數據庫根據這些關于數據庫所 存數據的統計數字來找出最好的辦法. 一旦制訂出查詢方案, 就可以由數據庫引擎來執行. 需要 CPU 來產生訪問方案. 想的情況, 如果我們把相同的語句給數據庫發送兩次, 我們期望 數據庫重用第一條記錄的訪問方案. 這會比第二次重新產生方案要使用較少的 CPU. 語句緩沖數據庫可以進行調節來做語句緩沖. 通常包含一些類型的語句緩沖. 緩沖使用語句本身作為關鍵 字, 訪問方案和相應的語句存儲在緩沖區中. 這樣就允許數據庫引擎 對以前執行過的語句所使用 的訪問方案進行重用. 舉個例子來說, 如果我們向數據庫發送這樣一條語句 "select a, b from t where c = 2", 計算好的訪問方案就放入緩沖區了. 如果我們以后再使用同樣的語 句, 數據庫就能重用以前的訪問方案, 這樣就能節省 CPU. 但是要注意, 整條語句是一個關鍵字. 例如, 如果我們后來發送的語句是 "select a,b from t where c = 3", 那么就不會找出以前的訪問方案. 因為 "c=3" 和 "c=2" 是不一 樣的. 所以, 例如: For(int I = 0; I < 1000; ++I) { PreparedStatement ps = conn.prepareStatement("select a,b from t where c = " + I); ResultSet rs = Ps.executeQuery(); Rs.close(); Ps.close(); } 這里不會用到緩沖. 每次循環向數據庫發送一條不同的 SQL 語句. 每次循環都重新計算新的訪問 方案, 用這種方法我們會浪費大量的 CPU 周期. 但是, 看看下一個片段: PreparedStatement ps = conn.prepareStatement("select a,b from t where c = ?"); For(int I = 0; I < 1000; ++I) { ps.setInt(1, I); ResultSet rs = ps.executeQuery(); Rs.close(); } ps.close(); 這樣就會高效得多. 發送給數據庫的語句在 sql 中使用 @#?@# 符號來參數化. 這意味著每次循環 發送是同一條語句, 在 "c=?" 部分帶有不同的參數. 這樣就允許數據庫重用語句的訪問方案, 是程序在數據庫內部運行得更高效. 這基本上能使你的程序 運行得更快, 或者使數據庫用戶能更多 地使用 CPU. PreparedStatement 和 J2EE 服務器當我們使用 J2EE 服務器的時候, 事情會變得更加復雜. 通常情況下, 一個預先準備好的語句 (prepared statement) 是和一個單獨的數據庫連接相關聯的. 當連接關閉時, 語句就被丟棄 了. 一般來說, 一個胖客戶端應用程序在得到一個數據庫連接后會一 直保持到程序結束. 它會使用 兩種方法創建所有的語句: 急切創建(eagerly) 或者 懶惰創建(lazily). Eagerly是說, 當程序啟動時全部創建. Lazily是說隨用隨創建. 急切的方法會在程序啟動時有些延時, 但是一旦程序啟動以后, 運行很好. 懶惰的方法啟動很快, 但是當程序運行時, 預先準備的語句在第一次使用是創建. 這就會造成性能 不平衡, 知道所有的 語句都準備好了, 但是最終程序會和急切方法一樣快. 哪一種最好要看你需要的是快速啟動還是 均衡的性能. 一個 J2EE 應用程序所帶來的問題就是它不能像這樣工作. 它只在一個請求的生存時間中保持一個 連接. 這意味著在他處理每一個請求時都會重新創建語句, 就不象胖客戶端只創建一次, 而不是每 個請求都創建那樣有效, 當 J2EE 服務器給你的程序一個連接時, 并不是一個真正的連接, 而是一個經過包裝的. 你可以通過查看那個連接的類的名字來檢驗一下. 它不是一個數據庫的 JDBC 連接, 是你的服務器創建 的一個類. 通常, 如果你調用一個連接的 close 方法, 那么 jdbc 驅動程序會關閉這個連接. 我們希望的是當 J2EE 應用程序調用 close 的時候, 連接會返回到連接池中. 我們通過設計一個 代理的 jdbc 連接類來做這些, 但看起來 就象是實際的連接. 當我們調用這個連接的任何方法時, 代理類就會把請求前遞給 實際的連接. 但是, 當我們調用類似 close 的方法時, 并不調用實際 連接的 close 方法, 只是簡單地把連接返回給連接池, 然后把代理連接標記為無效, 這樣當它 被應用程序重新使用時, 我們會得到異常.包裝是非常有用的, 因為它幫助J2EE 應用程序服務器實現者比較聰明地加上預先準備語句的 支持. 當程序調用Connection.prepareStatement 時, 由驅動程序返回一 個 PreparedStatement 對象. 當應用程序得到它時, 保存這個句柄, 并且在請求完成時, 關閉 請求之前關閉這個句柄. 但是, 在連接返回到連接池之后, 以后被同樣或者 另一個應用程序重用時, 那么, 我們就理論上希望同樣的 PreparedStatement 返回給 應用程序.當我們和數據庫建立連接之后,這個東東負責執行sql語句簡而言之,是負責執行sql的東東。
本文到此分享完畢,希望對大家有所幫助。