如果不存在JPA批量插入



我有3个实体- Player, Hand和PlayerHandStats。前两个是常规表,ID为PK。另一方面,PlayerHandStats有一个复合PK (player_id, hand_id)。它们一起形成了某种"包",这就是为什么我试图将它们持久化在一个块中。ParsedHand只是一个绑定实体的类-它包含1手,2…10玩家和2..10PlayerHandStats。下面是我目前的朴素方法,它实际上不起作用。

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

问题是,一个特定的播放器实体可能已经存在于数据库中-在这种情况下,整个过程终止。我想让它继续运行,不执行任何合并或更新实体,但检索它的ID(因为在应用程序级别它没有分配ID)。

快速示例(注意:列NAME和POKER_SITE形成一个UNIQUE约束):

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的经验很少,任何形式的帮助,或者指给我正确的方向都是非常感激的。谢谢你。

如果玩家可能是现有的玩家,那么对于每个玩家,你需要查询数据库中具有该名称和站点的玩家,如果存在则使用它,如果没有则持久化它

这取决于他们是这样一个玩家的可能性。如果不太可能,则可以持久化它,如果提交失败,则使用第二种算法重试。

一般来说,如果你的玩家有自己的id就更好了,这样你就能知道它是新的还是现有的。

最新更新