簡體   English   中英

如何堅持很多實體(JPA)

[英]How to persist a lot of entities (JPA)

我需要處理一個CSV文件,並且每個記錄(行)都會保留一個實體。 現在,我這樣做:

while ((line = reader.readNext()) != null) {
    Entity entity = createEntityObject(line);
    entityManager.save(entity);
    i++;
}

其中save(Entity)方法基本上只是一個EntityManager.merge()調用。 CSV文件中大約有20,000個實體(行)。 這是一種有效的方法嗎? 這似乎很慢。 使用EntityManager.persist()會更好嗎? 這種解決方案是否有任何缺陷?

編輯

這是一個漫長的過程(超過400s),我嘗試了兩種解決方案, persistmerge 兩者的完成時間大致相同(459s vs 443s)。 問題是如果逐個保存實體是最佳的。 據我所知,Hibernate(我的JPA提供程序)確實實現了一些緩存/刷新功能,所以我不必擔心這一點。

JPA API沒有為您提供最佳選擇。 根據您想要的速度,您將不得不尋找特定於ORM的選項 - 在您的情況下使用Hibernate。

要檢查的事項:

  1. 檢查您是否正在使用單筆交易(是的,顯然您確定了這一點)
  2. 檢查您的JPA提供程序(Hibernate)是否正在使用JDBC批處理API(請參閱:hibernate.jdbc.batch_size)
  3. 檢查是否可以繞過獲取生成的密鑰(取決於db / jdbc驅動程序從中獲得多少好處 - 參考:hibernate.jdbc.use_getGeneratedKeys)
  4. 檢查是否可以繞過級聯邏輯(只有最小的性能優勢)

所以在Ebean ORM中這將是:

    EbeanServer server = Ebean.getServer(null);

    Transaction transaction = server.beginTransaction();
    try {
        // Use JDBC batch API with a batch size of 100
        transaction.setBatchSize(100);
        // Don't bother getting generated keys
        transaction.setBatchGetGeneratedKeys(false);
        // Skip cascading persist 
        transaction.setPersistCascade(false);

        // persist your beans ...
        Iterator<YourEntity> it = null; // obviously should not be null 
        while (it.hasNext()) {
            YourEntity yourEntity = it.next();
            server.save(yourEntity);
        }

        transaction.commit();
    } finally {
        transaction.end();
    }

哦,如果你通過原始JDBC執行此操作,則跳過ORM開銷(減少對象創建/垃圾收集等) - 所以我不會忽略該選項。

所以,是的,這不能回答您的問題,但可能有助於您搜索更多ORM特定的批量插入調整。

我認為這樣做的一種常見方式是交易。 如果您開始新事務然后持久存儲大量對象,則在提交事務之前,它們實際上不會插入到數據庫中。 如果您要提交大量項目,這可以提高效率。

查看EntityManager.getTransaction

您可以使用經典的SQL Insert語句將它們直接寫入數據庫。

@see EntityManager.createNativeQuery

為了使它更快,至少在Hibernate中,你會在一定數量的插入后執行flush()和clear()。 我已經為數百萬條記錄做了這種方法並且它有效。 它仍然很慢,但它比不這樣做要快得多。 基本結構是這樣的:

int i = 0;
for(MyThingy thingy : lotsOfThingies) {

    dao.save(thingy.toModel())

    if(++i % 20 == 0) {
        dao.flushAndClear();
    }

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM