質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
87.20%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Webサイト

一つのドメイン上に存在するWebページの集合体をWebサイトと呼びます。

受付中

JPAからのStoredProcedureコール

h.t.0210
h.t.0210

総合スコア6

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Webサイト

一つのドメイン上に存在するWebページの集合体をWebサイトと呼びます。

0回答

0評価

0クリップ

192閲覧

投稿2018/03/22 13:31

編集2022/01/12 10:55

前提・実現したいこと

複数件の依頼に対して、JPAのStoredProcedureQuryを利用して、
件数分プロシージャコールを行い登録する処理を実装しています。
全て成功した場合のみcommitという作りにしています。
データベースはOracleです。

発生している問題・エラーメッセージ

問題は、StoredProcedureQueryのexecuteメソッドを繰り返しコールすると、
その都度カーソルがオープンされてしまい、300に到達した時点でORA-01000(最大オープン・カーソル数を超えました。)でエラーになってしまっています。

該当のソースコード

lang

try{ fac = Persistence.createEntityManagerFactory("xxx"); em = fac.createEntityManager(); tx = em.getTransaction(); StoredProcedureQuery spq; spq = em.createStoredProcedureQuery("YYYY.ZZZZ"); spq.registerStoredProcedureParameter(1, Object.class, ParameterMode.IN); spq.registerStoredProcedureParameter(2, Object.class, ParameterMode.IN); spq.registerStoredProcedureParameter(3, Short.class, ParameterMode.OUT); spq.registerStoredProcedureParameter(4, Short.class, ParameterMode.OUT); tx.begin(); for (List<String> rec : csv) { String aa = rec.get(0); String bb= rec.get(1); spq.setParameter(1, aa); spq.setParameter(2, bb); // 実行 spq.execute(); // エラーチェック if(...){ tx.rollback(); return; } } tx.commit(); }catch(Exception e){ throw e; }finally{ if(em != null)em.close(); if(fac != null)fac.close(); }

lang

CREATE OR REPLACE PACKAGE YYYY AS /** ステータスコード **/ G_RET_NORMAL NUMBER := 0; G_RET_SQLERROR NUMBER := 1; G_RET_PARAMERTER NUMBER := 2; G_RET_DUPLICATION NUMBER := 3; G_RET_NO_EXIST NUMBER := 4; /** エラーNO **/ G_ERR_NO_SUCCESS NUMBER := 0; G_RET_ERROR NUMBER := 1; PROCEDURE ZZZZ ( I_AAA IN TABLE_A.AAA%type, I_BBB IN TABLE_A.BBB%type O_STATUS OUT NUMBER, O_ERROR_NO OUT NUMBER ); END YYYY; / CREATE OR REPLACE PACKAGE BODY YYYY IS PROCEDURE ZZZZ ( I_AAA IN TABLE_A.AAA%type, I_BBB IN TABLE_A.BBB%type O_STATUS OUT NUMBER, O_ERROR_NO OUT NUMBER ) IS nCOUNT NUMBER := 0; BEGIN /* 入力パラメータチェック */ ・・・ /* データ存在チェック */ BEGIN SELECT COUNT(1) INTO nCOUNT FROM TABLE_A WHERE AAA = I_AAA AND BBB = I_BBB ; EXCEPTION WHEN OTHERS THEN O_STATUS := G_RET_SQLERROR; O_ERROR_NO := SQLCODE ; RETURN ; END ; IF nCOUNT > 0 THEN O_STATUS := G_RET_DUPLICATION; O_ERROR_NO := G_RET_ERROR ; RETURN ; END IF; /* データ登録 */ BEGIN INSERT INTO TABLE_A ( AAA, BBB ) VALUES( I_AAA, I_BBB ); EXCEPTION WHEN OTHERS THEN O_STATUS := G_RET_SQLERROR; O_ERROR_NO := SQLCODE ; RETURN ; END ; O_STATUS := G_RET_NORMAL ; O_ERROR_NO := G_ERR_NO_SUCCESS ; RETURN ; EXCEPTION WHEN OTHERS THEN O_STATUS := G_RET_SQLERROR ; O_ERROR_NO := SQLCODE ; RETURN ; END ZZZZ; END YYYY; /

試したこと

プロシージャ内の処理を空にしても同様のエラーとなったため、おそらくプロシージャコール自体でカーソルを作成しているものと思われます。
V$OPEN_CURSORを確認したところ、確かに「BEGIN プロシージャ名; END;」というOPENが増幅していました。
JPAのStoredProcedureQueryを使わずにjava.sql.CallableStatementで呼び出したら、トランザクションの制御を含めてうまくいきましたので、JPA側の問題ではないかと思います。
ただ、コードの統一性を考慮して、実装はあくまでJPAで行いたいと考えています。

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

良い質問の評価を上げる

以下のような質問は評価を上げましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

気になる質問をクリップする

クリップした質問は、後からいつでもマイページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

  • プログラミングに関係のない質問
  • やってほしいことだけを記載した丸投げの質問
  • 問題・課題が含まれていない質問
  • 意図的に内容が抹消された質問
  • 過去に投稿した質問と同じ内容の質問
  • 広告と受け取られるような投稿

評価を下げると、トップページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

asahina1979

2018/03/22 14:26

ストアドの設計として間違えてるとしか思えないんだが
h.t.0210

2018/03/23 01:53

回答いただきありがとうございます。ストアドではトランザクションの制御は行わず、処理としては存在チェックをして、あればエラー、なければインサートをしています。
h.t.0210

2018/03/23 05:33

JPAのStoredProcedureQueryを使わずにjava.sql.CallableStatementで呼び出したら、トランザクションの制御を含めてうまくいきましたので、JPA側の問題ではないかと思います。
asahina1979

2018/03/23 13:28

ちなみにJPAの実装はサードパーティーに任されています。
h.t.0210

2018/03/30 09:15

開発期間も限られている為、CallableStatementで対応しました。そもそもJPAのストアドの対応がなされたのも最近のバージョンみたいなので、今回のような不具合?はあるのかもしれないですね。単に使い方の可能性の方が高いとは思いますが。。

まだ回答がついていません

会員登録して回答してみよう

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
87.20%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

同じタグがついた質問を見る

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Webサイト

一つのドメイン上に存在するWebページの集合体をWebサイトと呼びます。