Lesen von Daten aus SYS_REFCURSOR in einer Oracle-gespeicherten Prozedur und Wiederverwendung es in java
Ich habe diese Tabelle:
CREATE TABLE "QMS_MODEL"."BOOKING" (
"ID" NUMBER ( 19, 0 ) CONSTRAINT "QMS_BOOKING_NN_1" NOT NULL ENABLE
,"CALL_TIME" TIMESTAMP ( 6 )
);
Dann habe ich eine einfache gespeicherte Prozedur in Oracle:
1.Holen Sie sich einen Datensatz aus einer Tabelle
2.update einer Spalte, die auf den gefundenen Datensatz
3.zurück von einem OUT-parameter ein SYS_REFCURSOR, die Punkte auf den gefundenen Datensatz :
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;
Aufruf dieser Prozedur wird die Buchung gefunden
und das Feld aktualisiert wird,aber am Ende wird der cursor
ist nicht gültig und ich kann nicht es verwenden, für einen anderen Vorgang
in diesem Beispiel habe ich den cursor verwenden, um melden Sie das id-Feld
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;
Ich Modell die Buchung in java mittels einer Entität
@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 {
..
..
}
...und ich bekomme es von einem 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
}
die einzige Anforderung für mich sind
-wählen Sie die Buchung und aktualisieren Sie es in der gleichen Transaktion in einer gespeicherten Prozedur
-rufen Sie die gespeicherte Prozedur aus java und abrufen der aktualisierten Buchung in form eines @Entity-Buchung
vielen Dank im Voraus.
InformationsquelleAutor emmedierre | 2012-02-15
Du musst angemeldet sein, um einen Kommentar abzugeben.
Einen ref-cursor ist nicht wie die bildlauffähigen cursor, finden wir in der front-end-Sprachen. Es ist ein Zeiger auf ein resultset. Das heißt, wir können einmal gelesen und dann ist es erschöpft. Es ist nicht wiederverwendbar.
Okay, hier ist ein Ansatz. Warnung: dies ist proof-of-concept (d.h. ungetestete code) und werden nicht garantiert, um zu arbeiten, aber es scheint wie eine praktikable Lösung.
Grundsätzlich:
Sie zwei Abfragen, aber die Auswahl mit ROWID ist ziemlich schnell.
InformationsquelleAutor APC
Das problem ist bei (3) - zurück von einem OUT-parameter ein SYS_REFCURSOR, die Punkte auf den gefundenen Datensatz'. Es nicht zu, dass record da hast du
fetch
ed vorbei. Ich nehme an, Sie sind nur zu erwarten, ein einzelner Datensatz mit der ID sowieso; wenn Sie mehr als eine haben dann ist der zurückgegebene cursor auf das nächsten Datensatz mit dieser ID, aber Ihreupdate
wird aktualisiert haben, werden alle passenden Datensätze mit ID, nicht nur die, die Sie geholt.Wenn Sie nur einen einzelnen Datensatz, warum verwenden Sie einen cursor? Der einzige Grund, den ich sehen kann, ist, Ihnen zu erlauben, zu verwenden
for update
, aber Sie nicht mit den entsprechendenwhere current of
im update.where current of
; und wenn Sie mehr als einen brauchen Sie eineorder by
zu Steuern, welche Sie bekam. Wenn Sie könnten zuverlässig erhalten den gleichen Datensatz, den Sie aktualisieren, Sie in einen lokalen cursor, und öffnen Sie dann dieout
cursor für eine zweite identische select?Ich post eine vereinfachte version meiner Abfrage, in der real-version gibt es eine Klausel "... WHERE ROWNUM <= 1 " also ich habe 1 Ergebnis in output. Ich brauche eine sys_refcursor um einen gesamten Datensatz aus dem Verfahren, und binden Sie es zu einer Buchung Entität in Java (eine Regel ist, verwenden Sie die gespeicherte Prozedur im Ruhezustand : docs.jboss.org/hibernate/orm/3.3/reference/en/html/... ). Beachten Sie, dass die echte wählen kann hart sein, damit ich nicht ausführen möchten, Sie mehr als einmal (ich glaube, thah wieder zu öffnen, der cursor ist wie neu ausführen " wählen Sie ein zweites mal)
InformationsquelleAutor Alex Poole