JPA アプリケーションのトラブルシューティング
下記の情報は、Java™ パーシスタンス API (JPA) アプリケーションにおけるさまざまな既知の問題を検索する場合に使用します。
手順
- JPA シン・クライアント jar を使用する際、org.apache.openjpa.* クラスまたは com.ibm.websphere.persistence.* クラスの NoClassDefFoundError のトラブルシューティングを実行します。
WebSphere® Application Server バージョン 9.0 以降、使用可能な JPA シン・クライアント JAR ファイルが 2 つあります。 com.ibm.ws.jpa-2.1.thinclient_9.0.jar: JPA 2.1 仕様インターフェース、および EclipseLink のクラスとインターフェースが含まれています。 com.ibm.ws.jpa-2.0.thinclient_9.0.jar: JPA 2.0 仕様インターフェース、および WSJPA と OpenJPA のクラスとインターフェースが含まれています。 バージョン 9 より前の場合、この jar の名前は com.ibm.ws.jpa_X.X.jar でした。
トラブルの回避 (Avoid trouble):
アプリケーションが OpenJPA または WSJPA に固有のクラスや動作に依存していて、com.ibm.ws.jpa-2.1.thinclient_9.0.jar を classpath に追加した場合は、シン・クライアントの classpath には、代わりに com.ibm.ws.jpa-2.0.thinclient_9.0.jar を使用する必要があります。
gotcha - WebSphere Application Server で実行されているアプリケーションから、org.apache.openjpa.* クラスまたは com.ibm.websphere.persistence.* クラスの NoClassDefFoundError のトラブルシューティングを実行します。 WebSphere Application Server バージョン 9.0 では、新しいプロファイルのデフォルト・パーシスタンス・プロバイダーが OpenJPA から EclipseLink に変更されています。 WebSphere が EclipseLink を使用するように構成されている場合に OpenJPA アプリケーションを実行すると、NoClassDefFoundError になります。 アプリケーションが JPA 2.1 を使用するように構成されている場合、OpenJPA クラスはサーバー・ランタイムから利用できないためです。注: WebSphere Application Server バージョン 8.5.5 マイグレーション・ツールを使用して WebSphere Application Server バージョン 9.0 にマイグレーションする場合、JPA レベルは自動的に 2.0 に設定されます。 そこでは、WebSphere Application Server バージョン 8.5.5 と同じ JPA プロバイダーが使用されます。
この問題を解決するには、JPA 2.0 を使用するようにサーバーまたはクラスターを再構成します。 これにより、OpenJPA がデフォルト・パーシスタンス・プロバイダーとして設定されます。
- NoClassDefFoundError: org.apache.openjpa.enhance.PersistenceCapable のトラブルシューティングを実行します。
OpenJPA を使用するアプリケーションでは、エンティティー・クラスに対してビルド時拡張ツールを実行できます。
OpenJPA 拡張機能を使用すると、コンパイル済みクラスに対して org.apache.openjpa.enhance.PersistenceCapable などのクラスへの参照が追加されます。 WebSphere Application Server バージョン 9.0 では、新しいプロファイルのデフォルト・パーシスタンス・プロバイダーが OpenJPA から EclipseLink に変更されています。 WebSphere Application Server が EclipseLink を使用するように構成されている場合に OpenJPA 拡張アプリケーションを実行しようとすると、NoClassDefFoundError になります。 アプリケーションが JPA 2.1 を使用するように構成されている場合、OpenJPA クラスはサーバー・ランタイムから利用できないためです。注: WebSphere Application Server バージョン 8.5.5 マイグレーション・ツールを使用して WebSphere Application Server バージョン 9.0 にマイグレーションする場合、JPA レベルは自動的に 2.0 に設定されます。 そこでは、WebSphere Application Server バージョン 8.5.5 と同じ JPA プロバイダーが使用されます。この問題を解決するには、次のようにすることができます。
- JPA 2.0 を使用するようにサーバーまたはクラスターを再構成します。 これにより、OpenJPA がデフォルト・パーシスタンス・プロバイダーとして設定されます。
- アプリケーションを再コンパイルし、OpenJPA 拡張機能ではなく EclipseLink 拡張機能を使用してエンティティーを拡張します。
- トランザクションに関連するメッセージを確認します。
特定の条件下では、次のようなメッセージがログに記録されることがあります: WebSphere 管理トランザクションでは {0} を実行できません。(Unable to execute {0} on a WebSphere managed transaction.) WebSphere は、管理トランザクションの直接操作をサポートしません。
このエラーは、<non-jta-data-source> として正しく構成されていないデータ・ソースが原因で発生した可能性があります。 <non-jta-data-source> として使用されるデータ・ソースの構成方法に関するインフォメーション・センターのトピック『パーシスタンス・プロバイダーとデータ・ソースの関連付け』を参照してください。
- ランタイムによって拡張されていないクラスをトラブルシューティングします。
このようなシチュエーションの診断は難解です。 エンティティー・クラスの OpenJPA 拡張がないという問題をトレースで遡ることができる場合があります。 このようなシチュエーションの例として、エンティティーが「パーシスタンス可能」ではない場合を検出することがあります。 ログで次のようなメッセージを検索します。この構成ではランタイム最適化は許可されていませんが、以下にリストされたタイプは Java エージェントでビルド時、またはクラス・ロード時に拡張されていません: "{0}"。(This configuration disallows runtime optimization, but the following listed types were not enhanced at build time or at class load time with a Java agent: "{0}".)
このメッセージは、リストされたエンティティー・タイプにおいて期待されるランタイム拡張が実行されなかったことを示しています。 ほとんどの場合、このエラーは単なるビルド時の障害であり、リストされたクラスに対して PCEnhancer を実行する必要があります。 また、特にエンティティー拡張をするため、コンテナー・クラス・ローダーの変換が予期される場合、他の問題が関係していることも示している可能性があります。
- カーソルのクローズに関する実行をトラブルシューティングします。 ログ org.apache.openjpa.persistence.PersistenceException にある DB2® の例外を以下に示します。
[ibm][db2][jcc][10120][10898] Invalid operation: result set is closed can be a WebSphere Application Server の構成上の問題の可能性があります。
デフォルトでは、アプリケーション・サーバーはカスタム・プロパティー resultSetHoldability を 2 (CLOSE_CURSORS_AT_COMMIT) の値で構成します。このプロパティーにより、DB2 はトランザクションの境界でその結果セット/カーソルをクローズします。DB2 の resultSetHoldability のデフォルト値が 1 (HOLD_CURSORS_OVER_COMMIT) であるにもかかわらず、アプリケーション・サーバーはデフォルト値 2 を保持し、アプリケーション・サーバーの以前のリリースとの互換性を維持します。このデフォルトは変更できます。重要: このデータ・ソースが XA データ・ソースである場合は、そのデータ・ソースに新規のカスタム・プロパティーを、property_name = downgradeHoldCursorsUnderXa および boolean value = true と定義します。トラブルの回避 (Avoid trouble): バージョン 8.0 では、DB2 XA データ・ソースが使用されている場合は、「結果セットがクローズされている」問題を回避するために以下の構成が必要になります。
- DB2 バージョン 9.1 FP4 (APAR IZ18072 用) 以降のバージョンを使用します。
- カスタム・プロパティー name="downgradeHoldCursorsUnderXa"、value="true"、および type="java.lang.Boolean" を追加します。
- カスタム・プロパティー name="resultSetHoldability"、value="1"、および type="java.lang.Integer" を追加します。
- マルチスレッドでの EntityManager の使用を回避します。 以下のメッセージ・テキストの例外が発生する場合は、
複数のスレッドで EntityManager の使用を不用意にサポートしている可能性があります。
JPA 仕様によると、EntityManagers は単一スレッドで使用されるようになっています。 以下のような例外メッセージを受け取る場合があります (以下のコンテキストでは、ブローカーと EntityManagers は本質的に同じものです)。この問題の対処には、以下のような方法があります。
複数の並行スレッドが単一のブローカーにアクセスしようとしました。 デフォルトでは、ブローカーはスレッド・セーフではありません。単一のブローカーに複数のスレッドがアクセスする必要がある場合には、openjpa.Multithreaded プロパティーを true に設定し、デフォルトの動作をオーバーライドします。
ベスト・プラクティス: アプリケーション管理の (拡張) パーシスタンス・コンテキストを使用する場合に、取得/使用/クローズのパターンを使用します。 EntityManager を使用したメソッドを終了する前に、EntityManager は必ずクローズしてください。 EntityManager をオープンしたままにすると、その同じ EntityManager インスタンスを同時に別のスレッドが使用してしまう可能性があり、システム・リソースを消費してしまいます。bprac
- @PersistenceContext アノテーションを使用して EntityManager インスタンスを注入し、コンテナー管理パーシスタンスのコンテキストを使用するようアプリケーションを変更します (アプリケーションのプログラミング・モデルでこの変更が適用可能である場合)。 これで事実上、コンテナーによる管理をサポートすることで、取得/使用/クローズのパターンが使用されるようになります。
- 上記の例外テキストに示されているように、簡単な回避方法は、プロパティー openjpa.Multithreaded で EntityManagers へのマルチスレッド・アクセスを要求するように OpenJPAを構成することです。
このプロパティーを有効にすると、不要なオーバーヘッドがかかります。
トラブルの回避 (Avoid trouble): サーブレットのインスタンス変数は、サーブレットのすべてのインスタンスによって自動的に共有されます。 サーブレットのインスタンス変数で @PersistenceContext アノテーションを使用すると、意図せずに複数のスレッドが同じ EntityManager にアクセスすることがあります。また、この方法で注入された EntityManagers はすべて、アプリケーションが停止するまで、コンテナーによってクリーンアップされません。 サーブレットには、@PersistenceUnit アノテーションを使用して 1 つの EntityManagerFactory を注入する方法が適しています。gotcha
- オプティミスティック・ロックを使用している場合は、バージョン条件に注意してください。
JPA アーキテクチャーでは、パーシスタンス・プロバイダーはバージョン・プロパティーを使用してパーシスタンス・エンティティーのオプティミスティック・ロックおよび並行性セマンティクスを実行します。例えば、次のようにします。
@Entity public class VersionedTimestampEntity { @Id private int id; @Version private java.sql.Timestamp version; .... }
プロバイダーでは、エンティティーがデータベースに書き込まれると、バージョン・プロパティーを新規の値に更新します。 エンティティーのマージ・オペレーションでは、パーシスタンス・プロバイダーはこのバージョン管理プロパティーを検査し、マージ対象のエンティティーがエンティティーの不整合コピーであるかどうかを判別します。 不整合のバージョン条件によってこのオペレーションが失敗した場合は、OptimisticLockException が発生します。 バージョン・プロパティーの型は、以下のいずれかです。- int
- 整数
- short
- Short
- long
- Long
- Timestamp
エンティティーが永続化され、そのエンティティーが、そのプラットフォームの精度枠内の個別のパーシスタンス・コンテキスト内でフェッチされ更新される場合、 パーシスタンス・プロバイダーは、オプティミスティック・ロックおよび並行条件を検出できません。 その結果、OptimisticLockException がスローされず、データ保全性が損なわれる可能性があります。トラブルの回避 (Avoid trouble): バージョン・プロパティーに Timestamp 型を使用する場合は、Timestamp オブジェクトの作成に使用される実装精度から示される動作をアプリケーションが認識する必要があります。 典型的な実装は System.currentTimeMills メソッドを使用します。このメソッドの時間の精度は、 プラットフォーム固有です。例えば、この精度は、32 ビット Windows では 15 ミリ秒であり、z/OS® では 2 ミリ秒です。gotcha
- エンティティーを処理する際のデータベース制約違反をトラブルシューティングします。
WebSphere Application Server に組み込まれている JPA プロバイダー は、制約更新マネージャーを使用して、各エンティティーの構成に基づいて、データベースに対する SQL 要求の 順序を決定します。この更新マネージャーは、データベースに対する SQL 要求の順序を変更することができます。 これにより、アプリケーションでビジネス・ロジックの実行に必要なエンティティー・マネージャー操作の順序 を判別する負担が軽減され、基礎となるバッチ・サポートを使用して、データベースのパフォーマンスが最適化されます。
JPA プロバイダーは、エンティティー間のリレーションシップに暗黙のデータベース制約 があることを想定していないため、データベースに制約 (例えば、外部キー制約など) がある場合に、 望ましい順序で SQL ステートメントを実行できないことがあります。 このような状態の場合、以下の (またはこれと類似の) 例外が発生する可能性があります。com.ibm.db2.jcc.b.SqlException: DB2 SQL エラー: SQLCODE: -530、SQLSTATE: 23503、SQLERRMC: xxxxxx
この問題の対処には、以下のような方法があります。- 以下の構成プロパティーをパーシスタンス・ユニットに追加することにより、データベースから制約情報を読み取り、実行時に更新マネージャーに適用するように、OpenJPA プロバイダーを構成できます。
<property name="openjpa.jdbc.SchemaFactory" value="native(ForeignKeys=true)" />
- アプリケーションでエンティティーを拡張し、@ForeignKey アノテーションを使用して、どのリレーションシップに外部キー制約があるかを JPA プロバイダーに示すことができます。
public class Person { @ManyToOne @ForeignKey private Address address; .... }
- OpenJPA アプリケーションの場合、以下の構成プロパティーをパーシスタンス・ユニットに追加することにより、アプリケーションの責任で SQL ステートメントの順序を制御できます。
<property name="openjpa.jdbc.UpdateManager" value="operation-order" />
この構成オプションがある場合、JPA プロバイダーは、エンティティー操作が要求された順序と 同じ順序で SQL ステートメントを開始します。 アプリケーションでは、エンティティー間の相互依存に注意する必要があります。
トラブルの回避 (Avoid trouble): これらのプロパティーを組み合わせて使用したくなるかもしれませんが、ご使用の状況に最適なものを 1 つだけ使用してください。これらのプロパティーを組み合わせて使用する必要があると思われる状況の場合は、openjpa.jdbc.UpdateManager プロパティーと openjpa.jdbc.SchemaFactory プロパティーを両方とも使用すると、例外を修正するために必要な SQL 要求の順序にならないことがあるので注意してください。openjpa.jdbc.UpdateManager プロパティーの operation-order 設定は、アプリケーション内で指定された順序で SQL 要求を実行することを JPA プロバイダーに指示します。openjpa.jdbc.UpdateManager コマンドとともに openjpa.jdbc.SchemaFactory プロパティーを指定した場合でも、JPA プロバイダーは、SQL 要求を自動的に順序付けて、検出された制約 (外部キー制約など) を適用するのではなく、アプリケーションで指定された SQL 要求の順序を適用します。openjpa.jdbc.UpdateManager プロパティーを指定した場合は常に、SQL 要求がアプリケーション内で適切な順序で指定されるように、アプリケーション開発者が対処する必要があります。gotcha
- データベースから制約を除去します。
- 以下の構成プロパティーをパーシスタンス・ユニットに追加することにより、データベースから制約情報を読み取り、実行時に更新マネージャーに適用するように、OpenJPA プロバイダーを構成できます。
- OpenJPA MappingTool ANT タスクの使用をトラブルシューティングします。
OpenJPA により提供される MappingTool ANT タスクは、一時的なクラス・ローダーを使用して、 JDBC ドライバー・クラスをロードします。この一時的なクラス・ローダーで、DB2 などの一部の JDBC ドライバーのロード中に問題が生じることがあります。
MappingTool ANT タスクの実行時に、以下のようなエラーが表示されます。
[mappingtool] java.lang.UnsatisfiedLinkError: com/ibm/jvm/Trace.initTrace([Ljava/lang/String;[Ljava/lang/String;)V [mappingtool] at com.ibm.jvm.Trace.initializeTrace(Trace.java:94) [mappingtool] at com.ibm.jvm.Trace.<clinit>(Trace.java:59) [mappingtool] at java.lang.J9VMInternals.initializeImpl(Native Method) [mappingtool] at java.lang.J9VMInternals.initialize(J9VMInternals.java:200) [mappingtool] at java.lang.Class.forNameImpl(Native Method) [mappingtool] at java.lang.Class.forName(Class.java:136) [mappingtool] at com.ibm.db2.jcc.a.o.n(o.java:577) [mappingtool] at com.ibm.db2.jcc.a.o.<clinit>(o.java:329)マッピング・ツールを使用するために、tmpClassLoader=false 引数を ANT タスクに追加することにより、一時的なクラス・ローダーを使用不可にすることができます。以下に ANT スクリプト の例を 2 つ示します。
以下の例では、問題が発生します。
<taskdef name="mapping" classname="org.apache.openjpa.jdbc.ant.MappingToolTask" classpathref="jpa.cp"/> . . . <target name="map.broken"> <mapping> <!-- this exhibits the problem --> . . . </mapping> </target>
以下の例では、問題が発生しません。
<taskdef name="mapping" classname="org.apache.openjpa.jdbc.ant.MappingToolTask" classpathref="jpa.cp"/> . . . <target name="map.fixed"> <mapping tmpClassLoader="false"> <!-- this will work --> . . . </mapping> </target>
- 不整合なドメイン・モデルにおける DataCache の影響
アプリケーションが、不整合なドメイン・モデルを永続化して、後で別のパーシスタンス・コンテキストでエンティティーを取り出す場合、DataCache がアクティブであるかどうかによって、取り出されるエンティティーが異なります。
例えば、データベースの単一の外部キー列によってマップされる、2 つのエンティティー間の双方向で 1 対 1 のリレーションシップについて考えてみます。エンティティーの関係フィールドは、アプリケーションによって不整合に設定される可能性があります。 このような不整合な値がデータベースにマップされると、単一の外部キー列で双方向リレーションシップ DataCache がアクティブであると示されるため、データベース・レコードでは整合性が保たれます。ただし、DataCache では、メモリー内の不整合なエンティティー状態がキャプチャーされます。したがって、アプリケーションが、双方向リレーションで関連付けられている一組のエンティティーを永続化しており、それらのエンティティーの関係フィールドが不整合な値に設定されている場合に、後で別のパーシスタンス・コンテキストでエンティティーを取り出すと、双方向リレーションシップは、DataCache が使用されているかどうかによって、不整合のままか、整合性を持つようになるかのいずれかになります。
不整合なエンティティー状態が永続化されているのに、別のパーシスタンス・コンテキストでは 整合性がある状態で検索される別の例として、同じ列にマップされている複数のフィールドが、 異なる値に設定されている場合があります。 この場合も、DataCache を導入すると、別のパーシスタンス・コンテキストで実現されたエンティティーは不整合で異なる値を保持しますが、DataCache を使用しない場合、エンティティーは両方のフィールドで同じ値を保持します。
ベスト・プラクティス: アプリケーション・ドメイン・モデルに不整合な値を設定しないでください。OpenJPA の場合は、双方向リレーションシップのような特定の不整合を検出するように openjpa.InverseManager プロパティーを構成することによっても可能です。bprac
- MappingTool および @ForeignKey
アノテーションを Sybase とともに使用して、問題のトラブルシューティングを行います。
OpenJPA マッピング・ツールを Sybase Adaptive Server とともに使用する場合、外部キー制約は作成できません。このため、外部キー制約を手動で作成する必要があります。
- DB2 Optim™ pureQuery Runtime 構成オプションをトラブルシューティングします。 DB2 Optim pureQuery Runtime と合わせて WebSphere Application Server JPA (WSJPA) プロバイダーを使用する場合、persistence.xml ファイルで次のプロパティーを設定する必要があります。
<property name="openjpa.Compatibility" value="StrictIdentityValues=true"/>
例えば ReloadOnDetach=false のように、別の互換性オプションを設定する必要がある場合は、両方のオプションを、同一のプロパティー・ステートメントのパラメーターとして persistence.xml ファイルで指定する必要があります。以下に例を示します。
<property name="openjpa.Compatibility" value="StrictIdentityValues=true,ReloadOnDetach=false"/>
トラブルの回避 (Avoid trouble): OpenJPA 互換性プロパティーは、OpenJPA が特定のデータ型に対して生成するプロキシー型を削除しません (特に、GregorianCalendar などの日付型)。削除が行われないため、デシリアライゼーションの問題が生じることがあります。デシリアライゼーションの問題が生じた場合は、以下のメッセージのようなエラー・メッセージが発行されます。gotcha
Error Message is:org.codehaus.jackson.map.JsonMappingException: Can not construct instance of org.apache.openjpa.util.java$util$GregorianCalendar$proxy, problem: no suitable creator method found at [Source: org.apache.http.conn.EofSensorInputStream@d83fbd5; line: 1, column: 4094]
- データベースに DB2 for z/OS を使用している場合は、エンティティー内の時間関連の型属性での問題をトラブルシューティングします。 エンティティーに時間関連の型属性があり、データベースをターゲットとする、マップされる対応する列に互換性がない場合は、特定の状態で以下の例外が発生することがあります。
この例外は、次の場合に発生する可能性があります。org.apache.openjpa.lib.jdbc.ReportingSQLException: THE DATE, TIME, OR TIMESTAMP VALUE 1 IS INVALID. SQLCODE=-18x, SQLSTATE=22007
- データベースに DB2 for z/OS を実行している。
- 名前付き照会を使用していて、ネイティブ SQL でデータベースにアクセスする。
- ネイティブ照会で、時間関連のフィールドを SQL パラメーターとして使用しているが、この照会はデータベース表の列定義と互換性がない。互換性について詳しくは、DB2 9.7 インフォメーション・センターのトピックサポートされているデータ変換を参照してください。
サブトピック
JPA を使用したアプリケーションのロギング
ロギングは、アプリケーションのランタイム動作の表示、トレース、およびトラブルシューティングをサポートします。Java™ Persistence API (JPA) は、アプリケーション・サーバーに組み込まれた柔軟なロギング・システムを提供し、 問題のトラブルシューティングを支援します。JPA のデッドロックおよびトランザクション・タイムアウトのトラブルシューティング
データベースのデッドロックおよびトランザクション・タイムアウトは、同じデータベース・リソースにアクセスしようとする 2 つ以上のクライアント間での競合が原因となって発生します。 デッドロックは、2 つ以上のクライアント間で循環ブロッキング状態が発生し、互いにブロックし合って、どのクライアントも処理を進められないという、特殊な事例です。 これらの現象は、通常はプログラミング・エラーではありません。 これらは、複雑で相互に依存し合う方法でデータベース・リソースにアクセスするビジネス・ロジックが原因となっています。JPA を使用したアプリケーションのロギング
ロギングは、アプリケーションのランタイム動作の表示、トレース、およびトラブルシューティングをサポートします。Java™ Persistence API (JPA) は、アプリケーション・サーバーに組み込まれた柔軟なロギング・システムを提供し、 問題のトラブルシューティングを支援します。JPA のデッドロックおよびトランザクション・タイムアウトのトラブルシューティング
データベースのデッドロックおよびトランザクション・タイムアウトは、同じデータベース・リソースにアクセスしようとする 2 つ以上のクライアント間での競合が原因となって発生します。 デッドロックは、2 つ以上のクライアント間で循環ブロッキング状態が発生し、互いにブロックし合って、どのクライアントも処理を進められないという、特殊な事例です。 これらの現象は、通常はプログラミング・エラーではありません。 これらは、複雑で相互に依存し合う方法でデータベース・リソースにアクセスするビジネス・ロジックが原因となっています。


http://www14.software.ibm.com/webapp/wsbroker/redirect?version=cord&product=was-nd-mp&topic=tejb_jpatroubleshoot
ファイル名:tejb_jpatroubleshoot.html