【问题标题】:JPA bulk insert if not existsJPA 批量插入(如果不存在)
【发布时间】:2013-03-03 10:42:32
【问题描述】:

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

问题是,特定的 Player 实体可能已经存在于 DB 中 - 在这种情况下,整个过程将终止。我想继续它,不对实体执行任何合并或更新,而是检索它的 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 的经验很少,非常感谢任何形式的帮助,或者指出我正确的方向。谢谢。

【问题讨论】:

    标签: jpa persistent


    【解决方案1】:

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

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

    一般来说,如果你的播放器有它的 id 会更好,然后你就会知道它是新的还是现有的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-02-15
      • 1970-01-01
      • 1970-01-01
      • 2021-06-05
      • 2018-05-17
      • 1970-01-01
      • 1970-01-01
      • 2013-06-28
      相关资源
      最近更新 更多