3

Player、Hand、PlayerHandStatsの3つのエンティティがあります。最初の2つは、PKとしてIDを持つ通常のテーブルです。一方、PlayerHandStatsには複合PK(player_id、hand_id)があります。それらが一緒になってある種の「パッケージ」を形成するので、私はそれらを1つのブロックに永続化しようとしています。ParsedHandは、エンティティをバンドルする単なるクラスであり、1つのハンド、2..10のプレーヤー、および2..10のプレーヤーハンド統計が含まれています。以下は私の現在の素朴なアプローチですが、実際には機能しません。

public static void persist(ParsedHand parsedHand) {
    EntityManager em = emf.createEntityManager();
    em.getTransaction().begin();

    em.persist(parsedHand.getHand());

    Collection<Player> players = parsedHand.getPlayers().values();
    for (Player player : players) {
        em.persist(player);
    }

    Collection<PlayerHandStats> stats = parsedHand.getStats().values();
    for (PlayerHandStats phs : stats) {
        em.persist(stats);
    }

    em.getTransaction().commit();
    em.close();
}

問題は、特定のPlayerエンティティがDBにすでに存在している可能性があることです。その場合、プロセス全体が終了します。エンティティに対してマージや更新を実行せずに、そのIDを取得します(アプリケーションレベルではIDが割り当てられていないため)。

簡単な例(:NAME列とPOKER_SITE列は一意の制約を形成します):

ID  |NAME        |POKER_SITE
----+------------+------------
0   |neverlimp92 |PokerStars
1   |player01    |PokerStars

ここで、フィールド(null、'neverlimp92'、'PokerStars')を持つアプリケーションレベルのPlayerエンティティがあるとします。明らかに、java.sql.SQLIntegrityConstraintViolationExceptionが返され、プロセス全体が終了します。どうすればこれを回避できますか?hashCode()メソッドとequals()メソッドをオーバーライドして、実行する必要があります

for (Player player : playes) {
    if (!em.contains(player)) {
        em.persist(player);
    }
}

10k、さらには100kの行が存在する可能性があることを考えると、これが賢明なことかどうかはわかりません。

また、エンティティが存在する場合、そのIDを取得し、アプリケーションレベルで既存のインスタンスに割り当てる適切な方法は何ですか?

私はJPAの経験がほとんどないので、どんな種類の助けも、または正しい方向に私を向けることができれば幸いです。ありがとうございました。

4

1 に答える 1