2013-10-06 157 views
0

親愛的計算器社區更換甲骨文的「OracleTypes.CURSOR」爲等效在MySQL

我想升級使用Oracle數據庫到MySQL數據庫在JAVA開發的系統。

我已經到了使用存儲過程的地步,java代碼使用特定的oracle結構 - OracleTypes.CURSOR。請參閱下面的代碼。

private int getUserID(String username) { 
    int UserID = -1; 
    CallableStatement cs = null; 
    ResultSet rs = null; 
    try { 
     con = this.getConnection(); 
     cs = con.prepareCall("{call getUserID(?,?)}"); 
     cs.setString(1, username); 
     cs.registerOutParameter(2, OracleTypes.CURSOR); 
     cs.execute(); 
     rs = (ResultSet) cs.getObject(2); 

     if (rs.next()) { 
      UserID = rs.getInt(1); 
     } 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } finally { 
     try { 
      cs.close(); 
      rs.close(); 
     } catch (SQLException ex) { 
      Logger.getLogger(DBConnector.class.getName()).log(Level.SEVERE, null, ex); 
     } 
     closeConnection(); 
     return UserID; 
    } 
} 

我所試圖做的是利用OracleTypes.CURSOR轉換爲現在MySQL友好。 我的確讀過它可能會在新版本的mysql中做到這一點,所以我甚至試圖用java.sql.Types.INTEGER代替OracleTypes.CURSOR而沒有任何結果。

你能幫我嗎?

注:我這裏有以下的堆棧溢出以前的信息以及其他地方,如: http://bugs.mysql.com/bug.php?id=17898

+0

參數'OracleTypes.CURSOR'表示過程有一個「ref cursor」作爲out參數。我不認爲MySQL支持類似的概念。 –

+0

感謝您的評論。這也是我在尋找這個問題時最初的理解。但在我提供的鏈接上,我也獲得了現在支持的信息......不知何故。你對此有更多瞭解嗎? – pvt

+0

問題不在於參數,它是遊標類型作爲參數。事實上,你已經嘗試用一個整數代替它,這表明你不明白光標是什麼。遊標本質上代表一個結果集,它可以讓你滾動瀏覽它。 – Laurence

回答

1

MySql的不幸沒有實現ref cursors

然而,在MySQL存儲過程可以返回一個結果給客戶端,請參閱以下鏈接:http://dev.mysql.com/doc/refman/5.6/en/faqs-stored-procs.html#qandaitem-B-4-1-14

B.4.14:可以的MySQL 5.6的存儲程序返回的結果集?
存儲過程可以,但存儲的功能不能。如果您在存儲過程中執行普通SELECT,則結果集將直接返回給客戶端。

只需運行一個普通SELECT - 並將結果集返回給客戶端。

resulset與Oracle中的ref cursor非常類似。最顯着的區別是,在MySql中,結果集是從服務器完全檢索到客戶端並存儲在客戶端的內存中(而Oracle cursors以塊爲單位檢索行)。
然而,MySQL能夠模擬這種行爲(有一些限制),看到此鏈接:http://dev.mysql.com/doc/connector-j/en/connector-j-reference-implementation-notes.html

的ResultSet
默認情況下,結果集是完全檢索和存儲在內存中。在大多數情況下,這是最有效的操作方式,並且由於MySQL網絡協議的設計更容易實現。如果您正在使用具有大量行或大值的ResultSets,並且無法在您的JVM中爲需要的內存分配堆空間,那麼您可以告訴驅動程序一次將結果串流回一行。

要啓用此功能,以下面的方式創建Statement實例:

stmt = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY, 
       java.sql.ResultSet.CONCUR_READ_ONLY); 
stmt.setFetchSize(Integer.MIN_VALUE); 

的僅向前的組合,只讀結果集,並且Integer.MIN_VALUE的的提取大小作爲發信號給驅動程序以逐行地傳送結果集。在此之後,使用該語句創建的任何結果集都將逐行檢索。



它是如何工作 - 一個例子。

說,我們有我們要遷移到MySQL Oracle過程:

create or replace procedure getUserId(p_name varchar2, p_ref OUT sys_refcursor) 
is 
begin 
    open p_ref for 
    select id, username from users 
    where username = p_name; 
end; 
/

在MySQL這個過程可能是這樣的:

delimiter %% 
drop procedure if exists getUserId %% 
create procedure getUserId(p_name varchar(100)) 
begin 
    SELECT id, username FROM users 
    WHERE username = p_name; 
end;%% 
delimiter ; 

和代碼在Java中 - 基於從一個例子文檔:http://dev.mysql.com/doc/connector-j/en/connector-j-usagenotes-statements-callable.html#connector-j-examples-retrieving-results-params

 cs = conn.prepareCall("{call getUserID(?)}"); 
     cs.setString(1, "user1"); 
     boolean hasResultSet = cs.execute(); 
     if(hasResultSet){ 
      rs = cs.getResultSet(); 
      if (rs.next()) { 
       userId = rs.getInt(1); 
      } 
      System.out.println("Userid = " + userId); 
     } 
+0

我將測試此解決方案並在此處報告以讓社區知道它是否適用於我的遷移。不過謝謝你提供這樣一個全面的答案! – pvt

+0

我標記你的答案是正確的,抱歉等待很長時間,因爲我相信它應該可以幫助剩餘的用戶解決與CURSOR相關的問題。謝謝! – pvt