lire des données à partir de SYS_REFCURSOR dans une procédure stockée Oracle et le réutiliser dans java
J'ai cette table:
CREATE TABLE "QMS_MODEL"."BOOKING" (
"ID" NUMBER ( 19, 0 ) CONSTRAINT "QMS_BOOKING_NN_1" NOT NULL ENABLE
,"CALL_TIME" TIMESTAMP ( 6 )
);
Puis j'ai une simple procédure stockée Oracle que:
1.obtenir un enregistrement d'une table
2.mise à jour d'une colonne sur l'enregistrement trouvé
3.retour par un paramètre de SORTIE d'un SYS_REFCURSOR que les points à l'enregistrement trouvé :
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;
L'appel de cette procédure, la réservation est trouvé
et le champ est mis à jour,mais à la fin le curseur
n'est pas valide et je ne peux pas l'utiliser pour autre opération,
dans cet exemple, j'utilise le curseur pour ouvrir une session le champ 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;
J'modèle de la réservation en java à l'aide d'une entité
@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 {
..
..
}
...et je le reçois par un 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
}
la seule demande pour moi sont
-sélectionnez la réservation et le mettre à jour dans la même transaction dans une procédure stockée
-appel de la procédure stockée à partir de java et de récupérer la mise à jour de la réservation dans la forme d'un @Entity-Réservation
vous en remercie d'avance.
- S'il vous plaît, veuillez ne pas utiliser les citations lors de la création d'objets. Cela les rend sensibles à la casse et n'en finit pas de tracas.
Vous devez vous connecter pour publier un commentaire.
Un ref cursor n'est pas comme le curseur scrollable nous trouver en face d'extrémité langues. Il est un pointeur vers un objet resultset. Cela signifie, on peut lire une fois et puis il est épuisé. Il n'est pas réutilisable.
Ok, c'est une approche. Mise en garde: c'est la preuve de concept (c'est à dire le code non testé) et de ne pas garanti, mais il semble comme une solution possible.
En gros:
Vous ne numéro deux requêtes, mais les sélectionner à l'aide de ROWID est assez rapide.
Le problème est à (3) - retour par un paramètre de SORTIE d'un SYS_REFCURSOR que les points à l'enregistrement trouvé'. Il n'a pas de point à cet enregistrement parce que vous avez
fetch
ed passé. Je suis en supposant que vous êtes seulement en s'attendant à un seul enregistrement avec l'IDENTIFIANT de toute façon; si vous avez plus d'un, alors le curseur pointe vers la prochaine enregistrement avec l'IDENTIFIANT, mais votreupdate
aura mis à jour tous les enregistrements correspondant à cet ID, pas juste celui que vous avez récupéré.Si vous n'avez qu'un seul enregistrement, pourquoi utiliser un curseur? La seule raison que je vois est de vous permettre d'utiliser
for update
, mais vous n'êtes pas en utilisant le raccourciwhere current of
dans la mise à jour.where current of
; et si vous n'avez plus d'un, vous auriez besoin d'unorder by
pour contrôler que vous avez obtenu. Si vous pourrait sûrement obtenir le même rendu que vous pourriez mettre à jour dans un local curseur, puis ouvrez leout
curseur pour une deuxième identique choisir?