Получить выходной параметр из хранимой процедуры без вызова execute () - PullRequest
2 голосов
/ 01 августа 2020

Я хочу вызвать хранимую процедуру PL / SQL из программы Java через диспетчер сущностей:

StoredProcedureQuery storedProcedureQuery = entityManager.createStoredProcedureQuery("someProcedure");

Теперь я понял, что мне нужно вызвать execute () для этого storedProcedureQuery, чтобы выполнить процедуру и иметь возможность получить OUT-параметры. Однако я могу получить эти значения без вызова метода execute (), просто вызвав

someValue1 = (Integer)storedProcedureQuery.getOutputParameterValue(1);
someValue2 = (Integer)storedProcedureQuery.getOutputParameterValue(2);

Как это возможно? Когда именно хранимая процедура будет выполнена в этом фрагменте кода? Будет ли процедура выполняться каждые раз при вызове getOutputParameterValue ()? Есть ли официальная документация по такому поведению?

1 Ответ

1 голос
/ 01 августа 2020

Я новичок в своей области и мне так же любопытно, как и вам, вопрос. Однако я воспользовался этой возможностью, чтобы проверить это, и ниже мое наблюдение:

According to the documentation execute() returns:
> Return true if the first result corresponds to a result set,
> and false if it is an update count or if there are no results
> other than through IN OUT and OUT parameters, if any.

, поэтому я бы сказал, что возвращенное значение true или false не означает успешное или не выполнение.

Опять же, мы должны зарегистрировать параметры перед вызовом getOutputParameterValue. Если мы рассмотрим реализацию getOutputParameterValue, то сможем точно определить, где провайдер гибернации (в моем случае это JPA) вызывает фактическое выполнение.

Кроме того, сколько раз выполнялось выполнение Я протестировал его таким образом, чтобы проверить это, вставив в другую таблицу внутри вызывающей процедуры.

create table test_procedure_call(msg varchar2(100));

CREATE OR REPLACE PROCEDURE test (
    p_in_1  IN    NUMBER,
    p_out_1 OUT   VARCHAR2,
    p_out_2 OUT   VARCHAR2
) AS
BEGIN
    insert into test_procedure_call values ('Executed..');
    commit;
    select 'FirstName'||' '||'LastName','HR' into p_out_1,p_out_2 
      from dual 
     where p_in_1=1;
END;
/

@Test
    public void testStoredProcedureQuery() {
        StoredProcedureQuery sp = em.createStoredProcedureQuery("test");
        // set parameters
        sp.registerStoredProcedureParameter("p_in_1", Integer.class, ParameterMode.IN);
        sp.registerStoredProcedureParameter("p_out_1", String.class, ParameterMode.OUT);
        sp.registerStoredProcedureParameter("p_out_2", String.class, ParameterMode.OUT);
        sp.setParameter("p_in_1", 1);

        String name = sp.getOutputParameterValue("p_out_1").toString();
        String dept = sp.getOutputParameterValue("p_out_2").toString();

        System.out.println("Name : " + name);
        System.out.println("Department : " + dept);
    }

select * from test_procedure_call;

MSG                                                                                                 
----------------------------------------------------------------------------------------
Executed..

Таким образом, вне таблицы test_procedure_call, мы можем подтвердить, что он выполняется только один раз за тест. (как мы видели в примере выше).

...