2012-02-15 75 views
1

重用我有這個表:從SYS_REFCURSOR在Oracle存儲過程中讀取數據,並在Java

CREATE TABLE "QMS_MODEL"."BOOKING" (
     "ID" NUMBER (19, 0) CONSTRAINT "QMS_BOOKING_NN_1" NOT NULL ENABLE 
     ,"CALL_TIME" TIMESTAMP (6) 
); 

然後,我在Oracle中,一個簡單的存儲過程: 1.get記錄從表中 通過OUT參數2.更新上找到的記錄 3.returns一列SYS_REFCURSOR指向找到的記錄:

CREATE OR REPLACE 
PROCEDURE GET_BOOKING 
    ( 
    refCursorValue OUT SYS_REFCURSOR, 
    bookingId IN QMS_MODEL.booking.id%type 
) 
AS 
    bookingResult QMS_MODEL.booking%ROWTYPE; 
    todayAtNow QMS_MODEL.booking.booking_time%type; 
BEGIN 

    --******************************** 
    --get booking cursor.... 
    --******************************** 
    OPEN refCursorValue FOR 
    SELECT 
    bb.* 
    FROM qms_model.booking bb 
    WHERE bb.id = bookingId 
    FOR UPDATE; 


    --**************************************** 
    --from boking cursor get booking record... 
    --**************************************** 
    FETCH refCursorValue INTO bookingResult; 

    --******************************** 
    --update a column on found booking.... 
    --******************************** 
    SELECT SYSDATE into todayAtNow FROM DUAL; 
    UPDATE qms_model.booking SET 
      call_time = todayAtNow 
    WHERE id = bookingResult.id; 


    /* 
    after the fetch refCursorValue is not 
    valid and the client can't use it! 
    */ 

END; 

調用此過程中的預約發現 和字段被更新,但最後光標 是無效的,我不能在這個例子中使用它進行其他操作, 我使用光標登錄ID字段

set serveroutput on format wrapped; 
DECLARE 
    REFCURSORVALUE SYS_REFCURSOR; 
    BOOKINGID NUMBER; 
    bookingResult QMS_MODEL.booking%ROWTYPE; 
BEGIN 
    BOOKINGID := 184000000084539; 
    GET_BOOKING(
    REFCURSORVALUE, 
    BOOKINGID 
); 
    FETCH REFCURSORVALUE INTO bookingResult; 
    DBMS_OUTPUT.PUT_LINE('>>>OUT , cursor fetc,id='|| bookingResult.id); 
END; 

我預訂在Java中使用模型實體

@Entity 
@Table(name = "BOOKING", schema = "QMS_MODEL") 
@NamedNativeQueries({  
    @NamedNativeQuery(name = "booking.callNext.Oracle", 
    query = "call GET_BOOKING(?,:bookingId)", 
    callable = true, 
    resultClass = Booking.class) 
}) 
public class Booking implements Serializable { 
.. 
.. 
} 

...我用NamedNativeQuery得到它:

long bookingID=...some value 
Query q = entityMng.createNamedQuery("booking.callNext.Oracle"); 
q.setParameter("bookingId", bookingID); 
List results = q.getResultList(); 
if (results!=null && !results.isEmpty()) { 
    Booking eBooking = (Booking) results.get(0); 
    .. 
    .. 
    .. 
    ..i want use some booking data here.... 
    ..but i can't because the cursor is closed 
} 

我的唯一要求是 - 選擇預訂並在同一交易中將其更新到存儲過程中 -從java調用存儲過程並以@Entity-Booking的形式檢索更新的預訂

預先感謝您。

+1

請在創建對象時不要使用引號。它使得它們區分大小寫,並且不會引起麻煩。 – Ben 2012-02-15 11:44:58

回答

2

引用遊標不像我們在前端語言中找到的可滾動遊標。它是一個指向結果集的指針。這意味着,我們可以閱讀一次,然後用盡。它不可重用。

「當選擇了預約我需要更新call_time將其標記爲 ‘選擇’。當預訂有一個非空call_time不可選 了。我需要返回更新記錄Java應用程序 ,所以我需要把它作爲返回程序的第一參數 OUT sys_refcursor類型。

「需要注意的是真正的選擇可能會很辛苦,所以我不希望執行 它不止一次「

好的,這是一種方法。警告:這是概念驗證(即未經測試的代碼),並不保證能夠正常工作,但它似乎是一種可行的解決方案。

​​

基本上是:

  1. 更新的行(或多個)要選擇
  2. 使用returning子句來捕捉更新的行
  3. 的的rowid然後使用的rowid打開REFCURSOR只選擇更新的行。

您確實發出了兩個查詢,但使用ROWID選擇的速度相當快。

+0

當預訂被選中時,我需要更新call_time以將其標記爲「已選擇」。當預訂有非空call_time時,不再可選。 我需要將更新後的記錄返回給java應用程序,所以我需要將它作爲OUT「sys_refcursor」類型的過程的第一個參數返回。 (參見http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/querysql.html)。我不知道是否有一種方法可以在select中使用%rowtype,然後在輸出中使用「sys_refcursor」。 – emmedierre 2012-02-15 13:35:28

1

問題出在(3) - '通過OUT參數返回一個SYS_REFCURSOR指向找到的記錄'。它沒有指向那條記錄,因爲你已經通過了fetch。我假設你只用一個ID就可以得到一個記錄;如果您有多個,則返回的光標將指向具有該ID的下一個記錄,但您的update將更新具有該ID的所有匹配記錄,而不僅僅是您獲取的記錄。

如果您只有一條記錄,爲什麼要使用遊標?我能看到的唯一原因是允許您使用for update,但是您沒有在更新中使用相應的where current of

+0

@ user1210761 - 好的,如果返回記錄類型不可行。但是你仍然無法獲取並返回相同的遊標;如果ID不是唯一的,你仍然可能會更新多行,因爲你沒有使用'where current of';如果你確實有不止一個,你需要一個'order by'來控制你得到的。如果你可以可靠地獲得相同的記錄,你可以在本地光標中更新它,然後打開「out」光標進行第二個相同的選擇? – 2012-02-15 13:30:15

+0

我發佈了我的查詢的簡化版本,在真實版本中有一個子句「... WHERE ROWNUM <= 1」,所以我有1個輸出結果。我需要一個sys_refcursor從程序中獲取整個記錄,並將其綁定到Java中的Booking實體(是在hibernate中使用存儲過程的規則:http://docs.jboss.org/hibernate/orm/3.3/reference/ en/html/querysql.html)。請注意,真正的選擇可能很難,所以我不想多執行一次(我認爲重新打開遊標就像重新執行選擇第二次) – emmedierre 2012-02-15 13:45:23

相關問題