Statement 和 PreparedStatement CallableStatement及hibernate中的session

來源:互聯網
上載者:User

 JDBC驅動的最佳化是基於使用的是什麼功能. 選擇PreparedStatement還是Statement取決於你要怎麼使用它們. 對於只執行一次的SQL語句選擇Statement是最好的. 相反, 如果SQL語句被多次執行選用PreparedStatement是最好的.
對於PreparedStatement加?再set否則和statement一樣,就沒有效果。資料庫在執行sql語句的時候如果使用PreparedStatement語句會有一點優勢:因為資料庫會preparedStatement 語句進行先行編譯,下次執行相同的sql語句時,資料庫端不會再進行先行編譯了,而直接用資料庫的緩衝區,提高資料訪問的效率(但盡量盡量採用使用?號的方式傳遞參數),如果sql語句只執行一次,以後不再複用建議使用statement
PreparedStatement的第一次執行消耗是很高的. 它的效能體現在後面的重複執行.

CallableStatement用於執行 SQL 預存程序的介面

.PreparedStatement是先行編譯的,對於批量處理可以大大提高效率. 也叫JDBC預存程序

2. 使用 Statement 對象。在對資料庫只執行一次性存取的時侯,用 Statement 對象進行處理。PreparedStatement 對象的開銷比Statement大,對於一次性操作並不會帶來額外的好處。3.statement每次執行sql語句,相關資料庫都要執行sql語句的編譯,preparedstatement是先行編譯得,    preparedstatement支援批處理

 

二、使用PreparedStatement的Batch功能
Update大量的資料時, 先Prepare一個INSERT語句再多次的執行, 會導致很多次的網路連接. 要減少JDBC的調用次數改善效能, 你可以使用PreparedStatement的AddBatch()方法一次性發送多個查詢給資料庫. 例如, 讓我們來比較一下下面的例子.

例 1: 多次執行Prepared Statement

 

 
  1. PreparedStatement ps = conn.prepareStatement(  
  2.    "INSERT into employees values (?, ?, ?)");  
  3.   
  4. for (n = 0; n < 100; n++) {  
  5.   
  6.   ps.setString(name[n]);  
  7.   ps.setLong(id[n]);  
  8.   ps.setInt(salary[n]);  
  9.   ps.executeUpdate();  
  10. }  

 

例 2: 使用Batch

 

 
  1. PreparedStatement ps = conn.prepareStatement(  
  2.    "INSERT into employees values (?, ?, ?)");  
  3.   
  4. for (n = 0; n < 100; n++) {  
  5.   
  6.   ps.setString(name[n]);  
  7.   ps.setLong(id[n]);  
  8.   ps.setInt(salary[n]);  
  9.   ps.addBatch();  
  10. }  
  11. ps.executeBatch();  

 

 

 void addBatch()

          將一組參數添加到此 PreparedStatement 對象的批處理命令中。
 void clearParameters()

          立即清除當前參數值。
 boolean execute()

          在此 PreparedStatement 對象中執行 SQL 陳述式,該語句可以是任何種類的 SQL 陳述式。
 ResultSet executeQuery()

          在此 PreparedStatement 對象中執行 SQL 查詢,並返回該查詢產生的 ResultSet 對象。
 int executeUpdate()

          在此 PreparedStatement 對象中執行 SQL 陳述式,該語句必須是一個 SQL 資料操作語言(Data Manipulation Language,DML)語句,比如
INSERTUPDATEDELETE 語句;或者是無返回內容的 SQL 陳述式,比如 DDL 語句。

 

以上是preperStatement的幾個常用方法。

 

 execute  executeQuery、executeUpdate都是 SQL 陳述式的方法,區別如下:

       方法execute:
       用於執行返回多個結果集、多個更新計數或二者組合的語句。

       方法executeQuery
       用於產生單個結果集的語句,例如 SELECT 語句。這個方法被用來執行 SELECT 語句,它幾乎是使用最多的 SQL 陳述式。

       方法executeUpdate
       用於執行 INSERT、UPDATE 或 DELETE 語句以及 SQL DDL(資料定義語言 (Data Definition Language))語句,例如 CREATE TABLE 和 DROP TABLE。INSERT、UPDATE 或 DELETE 語句的效果是修改表中零行或多行中的一列或多列。executeUpdate 的傳回值是一個整數,指示受影響的行數(即更新計數)。對於 CREATE TABLE 或 DROP TABLE 等不操作行的語句,executeUpdate 的傳回值總為零。

      

 

 在例 1中, PreparedStatement被用來多次執行INSERT語句. 在這裡, 執行了100次INSERT操作, 共有101次網路往返. 其中,1次往返是預儲statement, 另外100次往返執行每個迭代. 在例2中, 當在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需要控制在一定的限度。

有人主張,在JDBC應用中,如果你已經是稍有水平開發人員,你就應該始終以PreparedStatement代替Statement.也就是說,在任何時候都不要使用Statement。

當一個 資料庫接收 到一條語句的時候, 資料庫引擎首先解析這條語句, 查看語法錯誤. 一 旦語句解析了,
資料庫 需要找出最有效方法來執行這條語句. 這個計算起來代價很大. 資料庫檢查什麼索引(如果有 的話)能有所協助, 或者它是否能全部讀出一張表中所有的記錄. 資料庫根據這些關於資料庫所 存資料的統計數字來找出最好的辦法. 一旦制訂出查詢方案, 就可以由資料庫引擎來執行. 需要 CPU 來產生訪問方案. 想的情況, 如果我們把相同的語句給資料庫發送兩次, 我們期望 資料庫重用第一條記錄的訪問方案. 這會比第二次重新產生方案要使用較少的 CPU. 語句緩衝資料庫可以進行調節來做語句緩衝. 通常包含一些類型的語句緩衝.
緩衝使用語句本身作為關鍵 字, 訪問方案和相應的語句儲存在緩衝區中. 這樣就允許資料庫引擎

由於preparedstatement具備很多優點,開發人員可能通常都使用它,只有在完全是因為效能原因或者是在一行sql語句中沒有變數的時候才使用通常的statement

對以前執行過的語句所使用 的訪問方案進行重用. 舉個例子來說, 如果我們向資料庫發送這樣一條語句 "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 伺服器

傳送給資料庫的 SQL 陳述式通過一個包含兩個步驟的過程來返回結果。首先準備它們,然後處理它們。藉助 Statement 對象,這兩個階段對應用程式而言變成一個階段。PreparedStatement 允許將這兩個步驟分開。準備步驟在建立對象時發生,而處理步驟在對 PreparedStatement 對象調用 executeQuery、executeUpdate 或 execute 方法時發生。

如果不添加參數標記,能夠將 SQL 處理分割成單獨的階段並沒有意義。參數標記放在應用程式中,從而使它能夠告訴資料庫它在準備時並不具有特定的值,但它在處理之前提供一個值。在 SQL 陳述式中,參數標記是使用問號表示的。

通過使用參數標記,有可能建立用於特定請求的一般 SQL 陳述式。例如,給定以下 SQL 查詢語句:

     SELECT * FROM EMPLOYEE_TABLE WHERE LASTNAME = 'DETTINGER'

這是一個特定的 SQL 陳述式,它只返回一個值;即關於名為 Dettinger 的僱員的資訊。通過添加參數標記,可以使語句更為靈活:

     SELECT * FROM EMPLOYEE_TABLE WHERE LASTNAME = ?

通過簡單地將參數標記設定為某個值,可以擷取關於表中的任何僱員的資訊。

由於前一個 Statement 樣本可以只經過一次準備階段並接著使用不同的參數值來重複地進行處理,所以 PreparedStatement 能夠提供比 Statement 更高的效能。

注意:要支援本機 JDBC 驅動程式的語句合用,必須使用 PreparedStatement。

prepareStatement 方法用來建立新的 PreparedStatement 對象。與 createStatement 方法不同,建立 PreparedStatement 對象時必須提供 SQL 陳述式。在那個時候,對 SQL 陳述式進行先行編譯以供使用。例如,假定已存在名為 conn 的 Connection 對象,以下樣本將建立 PreparedStatement 對象並準備要在資料庫中處理的 SQL 陳述式。

     PreparedStatement ps = conn.prepareStatement("SELECT * FROM EMPLOYEE_TABLE                                                  WHERE LASTNAME = ?");

與 createStatement 方法相同,重載 prepareStatement 方法的目的是提供對指定 ResultSet 特徵的支援。prepareStatement 方法還具有變體,可使用自動產生的鍵。以下是有效 prepareStatement 方法調用的一些樣本:

在可以處理 PreparedStatement 對象之前,必須將每個參數標記設定為一些值。PreparedStatement 對象提供了許多個用於設定參數的方法。所有這些方法的格式均為 set<Type>,其中 <Type> 是 Java 資料類型。這些方法的一些樣本包括 setInt、setLong、setString、setTimestamp、setNull 和 setBlob。幾乎所有這些方法都有兩個參數:

  • 第一個參數是該參數在語句中的索引。參數標記具有從 1 開始的編號。
  • 第二個參數是要對第一個參數設定的值。有幾個 set<Type> 方法具有附加的參數,如 setBinaryStream 上的長度參數。

 3:在hibernate中有以下幾種方法擷取connection和會話

首先要做hibernate中擷取SessionFactoryUtils.getSession(getSessionFactory(), true),及session。再通過

SessionFactoryUtils.getDataSource(getSessionFactory()).getConnection(),擷取串連。或者用session.connection(),但這個方法已經過時。

然後就是和jdbc都一樣的了。

但是hibernate還有專門的session可以進行資料庫的操作

1,一個使用者可以對應很多個SESSION ,但不一定對應一個connection (幾個session可能共用一個connection

connection是指使用者到資料庫建立起來的(物理)串連
2. session是指這個物理串連上的傳遞的資料,或者說session是一個邏輯上的串連
3,session >= connection

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.