2013-03-03 193 views
3

我有3个实体 - Player,Hand和PlayerHandStats。前两个是常规表,ID是PK。 PlayerHandStats另一方面有一个复合PK(player_id,hand_id)。他们一起形成某种“包裹”,这就是为什么我试图坚持他们在一个街区。 ParsedHand只是一个捆绑实体的类 - 它包含1个手,2个10个玩家和2个10个PlayerHandStats。以下是我当前的幼稚方法,但实际上并不奏效。JPA批量插入如果不存在

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)。

简单的例子(注意:列名和POKER_SITE形成一个唯一约束):

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

现在,让我们说我有在应用水平领域的一个Player实体(NULL, 'neverlimp92','扑克之星)。显然,它将返回java.sql.SQLIntegrityConstraintViolationException,并且整个过程终止。我怎样才能避免这种情况?我应该重写的hashCode()和equals()方法,并进行

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

我不知道这是做一个聪明的做法,考虑有可能是潜在的10K的,甚至100K的行。

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

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

回答

0

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

这取决于他们是多么可能是这样的球员。如果不太可能,那么你可以坚持下去,如果提交失败,则用第二种算法重试。

一般来说,如果你的玩家有自己的ID,那么你会知道它是新的还是现有的。