1

これについて同様の投稿がたくさんあることは知っていますが、私の問題に対する明確な答えを見つけることができませんでした。

できるだけ簡単にするために、私がそのようなエンティティを持っているとしましょう:

@Entity
public class Person implements Serializable {
  @Id
  private Long id;     // PK

  private String name; // business key

  /* getters and setters */

  /* 
     override equals() and hashCode() 
     to use the **name** field 
   */
}

つまり、idPKでnameあり、ビジネスキーです。保存したい名前のリストが重複している可能性があるとしましょう。名前ごとに1つのオブジェクトを作成し、JPAに永続化させると、最終的なテーブルに重複する名前が含まれることになります。これは受け入れられません。

私の質問は、以下で説明する代替案と(特に歓迎する)あなた自身の代替案を考慮して、あなたが最善のアプローチだと思うものです。

考えられる解決策1:エンティティマネージャーを確認する

新しい人物オブジェクトを作成する前に、同じ人物名のオブジェクトがすでに管理されているかどうかを確認してください。 問題:エンティティマネージャーはPKによってのみ照会できます。わからない回避策はありますか?

考えられる解決策2:クエリでオブジェクトを見つける

Query query = em.createQuery("SELECT p FROM Person p WHERE p.name = ...");
List<Person> list = query.getResultList();

質問:要求されたオブジェクトはすでにemにロードされている必要がありますが、これは引き続きデータベースからフェッチされますか?もしそうなら、クエリを解析するために、非常に頻繁に実行された場合、それでもあまり効率的ではないと思いますか?

考えられる解決策3:別の辞書を保持する

これが可能なのは、equals()とhashCode()がフィールドを使用するためにオーバーライドされるためnameです。

Map<String,Person> personDict = new HashMap<String,Person>();
for(String n : incomingNames) {
  Person p = personDict.get(n);
  if (p == null) {
    p = new Person();
    p.setName(n);
    em.persist(p);
    personDict.put(n,p);
  }
  // do something with it
}

問題1:大規模なコレクションのメモリを浪費します。これは基本的にエンティティマネージャが行うことです(ただし、完全ではありません)。

問題2:より複雑なスキーマがあり、最初の書き込み後にアプリケーションが閉じられて再起動され、データベースを再ロードする必要があるとします。すべてのテーブルが明示的にemにロードされている場合、ディクショナリを簡単に再入力できます(エンティティごとに1つ)が、レイジーフェッチやカスケード読み取りを使用する場合は、それほど簡単ではありません。

私は最近JPA(EclipseLinkを使用)を開始しました。この問題は非常に一般的な使用パターンに要約されるように思われるため、ここで基本的なものが欠落している可能性があります。

教えてください!

4

2 に答える 2

0

私が考えることができる最善の解決策は非常に単純です.Unique Constraintを使用してください

@Entity
@UniqueConstraint(columnNames="name")
public class Person implements Serializable {
    @Id
    private Long id;     // PK

    private String name; // business key
}
于 2012-08-30T17:04:15.133 に答える
0

フィールドをキーとして (正しく) 使用できるようにする唯一の方法は、そのフィールドに一意の制約を作成することです。@UniqueConstraint(columnNames="name")これは、または を使用して行うことができます@Column(unique = true)

重複キーを挿入しようとすると、EntityManager (実際には DB) が例外をスローします。このシナリオは、手動で設定された主キーにも当てはまります。

例外を防ぐ唯一の方法は、キーを選択して存在するかどうかを確認することです。

于 2012-08-31T05:20:53.553 に答える