如果不存在JPA批量插入

时间:2013-03-03 10:42:32

标签: jpa persistent

我有3个实体 - Player,Hand和PlayerHandStats。前两个是常规表,ID为PK。另一方面,PlayerHandStats有一个复合PK(player_id,hand_id)。它们一起构成某种“包”,这就是为什么我试图将它们保持在一个块中。 ParsedHand只是一个捆绑实体的类 - 它包含1个Hand,2..10 Player和2..10 PlayerHandStats。以下是我目前的天真方法,它并没有真正起作用。

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();
}

问题是,DB中可能已存在特定的Player实体 - 在这种情况下,整个过程终止。我想继续下去,不对实体执行任何合并或更新,但检索其ID(因为在应用程序级别它没有分配ID)。

快速示例(注意:列NAME和POKER_SITE构成一个独特的约束):

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

现在,假设我在应用程序级别有一个Player实体,包含字段(null,'neverlimp92','PokerStars')。显然,它将返回java.sql.SQLIntegrityConstraintViolationException,整个过程终止。我怎么能避免这个?我应该覆盖hashCode()和equals()方法,并执行

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

我不确定这是否是一个聪明的事情,考虑到可能有10k,甚至100k的行。

而且,如果实体确实存在,那么检索其ID并将其分配给应用程序级别的现有实例的正确方法是什么?

我对JPA的经验很少,任何形式的帮助,或者指向正确的方向都非常感激。谢谢。

1 个答案:

答案 0 :(得分:0)

如果玩家可能是现有玩家,那么对于每个玩家,您需要向具有该名称和站点的玩家查询数据库,如果存在,则使用它,如果不存在则继续使用它。

这取决于他们是这样一名球员的可能性。如果它不太可能,那么你可以坚持它,如果提交失败,那么用第二个算法重试。

一般情况下,如果您的玩家拥有其ID,那么您会知道它是新的还是现有的。