1

Java EE アプリケーションを開発しているときに、DB でエンティティが時期尚早に作成されたという 2 つの状況に遭遇しました。参照される行が挿入される前に挿入されたため、外部キー違反が発生しました。

最初は、DB に間違った順序で行を作成して、間違っていると思いました。
しかし、そうではありませんでした。それから、JPA プロバイダー* にバグがあるか、単に間違っているのではないかと考え始めました。
しかし、その後、EntityManager がテーブル間の接続を認識していないことに気付きました。

説明させてください:
どちらの状況でも、テーブル A は外部キーを使用してテーブル B を参照します。

状況 #1:

My code:
 1. Creates an entity of table B.
 2. Creates a row of table A using JDBC (there's no entity for table A).  
JPA provider:
 1. Runs the JDBC first (inserts a row into table A).
 2. SQLException is thrown, because B isn't created yet.

JDBC を使用する理由
それは私のコードではないからです。

状況 #2:

My code:
 1. Creates an entity of table B.
 2. Creates an entity of table A. The thing is, A only holds B's ID.
JPA provider:
 1. Creates entity A.
 2. SQLException is thrown, because B isn't created yet.

なぜ B は A をメンバーとして持っていないのですか?
B には大きなブロブがあり、多くのメモリを必要とするため、B オブジェクトへの参照を最小限に抑えたいと考えています。

解決策が必要です。おそらく、呼び出したのとまったく同じ順序でSQLを実行するようにEntityManagerに指示する方法があるでしょう。
トイレにいる間、エンティティ B を作成した後に「フラッシュ」を使用することも考えましたが、開発 DB がメンテナンスのために停止しているため (DBA が魔法を使っているため)、今はテストできません。

* Oracle WebLogic 12.1.1.0 に付属の TopLink を使用しています。

4

2 に答える 2

2

解決する良い方法は、A と B の間に関係を持つことです。それをより効率的にするためにできることは次のとおりです。

  • A から B への関係を遅延させる ( FetchType .LAZY)
  • B の blob フィールドを遅延させる
  • B への参照のみが必要な場合は、EntityManager.getReferenceを使用します。

何らかの理由で実行できない場合は、実行する必要がある各操作の後、後の操作の前に entitymanager をフラッシュする必要があります。

于 2012-05-13T13:12:14.817 に答える
1

リレーションシップを定義できない場合は、DescriptorCustomizer を使用して API addConstraintDependency() を呼び出して、EclipseLink に制約を通知すると、正しい順序で SQL が発行されます。

于 2012-05-14T19:08:23.460 に答える