2013-03-03 190 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,那麼你會知道它是新的還是現有的。