2012-02-15 76 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

相关问题