2009-09-01 121 views
3

我剛剛跳到由其他人編寫的功能上,看起來效率稍低,但我對JPA的瞭解不太適合找到不是Hibernate特定的便攜式解決方案。便攜式JPA批量/批量插入

簡而言之,在一個循環內調用的Dao方法插入每個新的實體都會執行一個「entityManager.merge(object);」。

Isnt'在JPA規範中定義的方式將實體列表傳遞給Dao方法,並執行批量/批量插入而不是爲每個對象調用合併?

另外,自從Dao方法被註釋爲w /「@Transactional」我想知道是否每個單獨的合併調用都在自己的事務中發生......這對性能沒有幫助。

有什麼想法?

回答

6

沒有香草JPA沒有批處理插入操作。

是的,每個插入將在其自己的事務中完成。 @Transactional屬性(沒有限定符)意味着REQUIRED的傳播級別(如果事務不存在,則創建事務)。假設你有:

public class Dao { 
    @Transactional 
    public void insert(SomeEntity entity) { 
    ... 
    } 
} 

你這樣做:

public class Batch { 
    private Dao dao; 

    @Transactional 
    public void insert(List<SomeEntity> entities) { 
    for (SomeEntity entity : entities) { 
     dao.insert(entity); 
    } 
    } 

    public void setDao(Dao dao) { 
    this.dao = dao; 
    } 
} 

這樣插入整組被包裹在一個單一的交易。如果您正在討論大量的插入操作,您可能需要將其拆分爲1000,1000組或其他任何作品,因爲足夠大的未提交事務可能會使資源數據庫癱瘓,並可能由於大小而失敗。

注意:@Transactional是一個Spring註釋。請參閱Spring Reference中的Transactional Management

+0

感謝您的回覆。在我的Dao方法中,它會幫助使用Persist()而不是Merge(),因爲它們是新實體? – Lancelot 2009-09-01 16:22:19

+0

merge()和persist()具有不同的語義。這不是一個簡單的問題,我強烈建議閱讀關於JPA的一些內容。 – cletus 2009-09-01 16:32:43

0

你可以做什麼,如果你是一個狡猾的心情是:

@Entity 
public class SomeEntityBatch { 

    @Id 
    @GeneratedValue 
    private int batchID; 
    @OneToMany(cascade = {PERSIST, MERGE}) 
    private List<SomeEntity> entities; 

    public SomeEntityBatch(List<SomeEntity> entities) { 
     this.entities = entities; 
    } 

} 

List<SomeEntity> entitiesToPersist; 
em.persist(new SomeEntityBatch(entitiesToPersist)); 
// remove the SomeEntityBatch object later 

因爲級聯,這將導致在一個單一的操作要插入的實體。

我懷疑這樣做是否有任何實際優勢,只需簡單地將單個對象保存在循環中即可。查看JPA實現發佈的SQL並進行基準測試將會很有趣。