2015年3月8日日曜日

JPA2.1でストアドプロシージャ実行-REF CURSOR編

JPA2.1でストアドプロシージャ実行の続編。
ストアドプロシージャで開いたカーソル(REF CURSOR)をJPA経由で受け取るサンプル。

実行対象のプロシージャ

パラメータは1つで、アウトパラメータでカーソルを返す。
CREATE OR REPLACE PROCEDURE REF_CURSOR_TEST(cur out SYS_REFCURSOR)
AS
BEGIN
    OPEN CUR FOR SELECT *
                 FROM USERS;
END;

実行例

EntityManagercreateStoredProcedureQueryにストアドプロシージャ名を指定してStoredProcedureQueryを生成します。
第2引数には、REF CURSORを受け取るEntityクラスを指定します。(Entity以外でもいいのか?)

executeでストアドプロシージャを実行して、getOutputParameterValueを呼び出してREF CURSORの結果を受け取ります。
ここで受け取ったEntityは管理対象となるので、状態を変更した場合は永続化層に反映される。
final StoredProcedureQuery query = em.createStoredProcedureQuery("REF_CURSOR_TEST", User.class)
         .registerStoredProcedureParameter(1, void.class, ParameterMode.REF_CURSOR);
query.execute();
List users = (List) query.getOutputParameterValue(1);

System.out.println("取得件数 = " + users.size());
users.forEach(user -> {
            System.out.println("id = " + user.getId());
            System.out.println("name = " + user.getName());
            user.setName(user.getName() + ":" + user.getId());
        }
);

実行結果

ストアドプロシージャで開いたカーソルの結果が受け取れていることがわかる。
[EL Fine]: sql: 2015-03-07 23:51:33.88--ClientSession(1620989914)--Connection(108049354)--Thread(Thread[main,5,main])--BEGIN REF_CURSOR_TEST(?); END;
 bind => [=> 1]
取得件数 = 2
id = 1
name = hoge
id = 2
name = fuga