2016-04-28 3 views
-1

エンティティマネージャ(プロバイダとしてのEclipselink)を使用してバッチを更新する方法を書いています。 ここで私が見つけたアプローチは Batch updates in JPA (Toplink)ここ(JPA - Batch/Bulk Update - What is the better approach?)ですが、私はspring Data JPAを使用していません。私はJPQLを使用する場合、エンティティはキャッシュに追加されません(それは正しいです。)私は次のアプローチを使用しています。しかし、それはより遅いです私が使用できる他のアプローチは?バッチを更新する一般的な方法を書いています。データベースとキャッシュとの同期のためのより良いアプローチを知りたい

@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW) 
public <T> void updatetBatch(List<T> list) { 
    if (list == null || list.isEmpty()) 
     throw new NullPointerException(); 
    EntityManager entityManager = entityManagerFactory.createEntityManager(); 
    final int BATCHLIMIT = 50; 

    try { 
     int size = list.size(); 
     for (int i = 0; i < size; i++) { 
      //Using find as it will make entity managed. 
      Object found=entityManager.find(list.get(i).getClass(), this.getPrimaryKey(list.get(i))); 
      if(found!=null) 
      entityManager.merge(list.get(i)); 
      if (i % BATCHLIMIT == 0) { 
       entityManager.flush(); 
       entityManager.clear(); 
      } 
     } 

    } catch (Exception e) { 
     e.printStackTrace(); 
    } finally { 
     entityManager.close(); 
    } 
} 
private Object getPrimaryKey(Object object) { 
    return entityManagerFactory.getPersistenceUnitUtil().getIdentifier(object); 
} 

ありがとうございます。ここで

答えて

0

があなたの修正コードで、

@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW) 
public <T> void updatetBatch(List<T> list) { 
    if (list == null || list.isEmpty()) 
     throw new NullPointerException(); 
    EntityManager entityManager = entityManagerFactory.createEntityManager(); 
    final int BATCHLIMIT = 50; 

    try { 
     int size = list.size(); 

     for (int i = 0; i < size; i++) { 
     Object primaryKeyObj = this.getPrimaryKey(list.get(i)); 
      //Using find as it will make entity managed. 
     T entityObject = list.get(i); 
      Object found = entityManager.find(entityObject.getClass(), primaryKeyObj); 
      if(found!=null) { 

       entityManager.merge(entityObject); 
     } else{ 
     entityManager.persist(entityObject); 
     } 
      if (i % BATCHLIMIT == 0) { 
       entityManager.flush(); 
       entityManager.clear(); 
      } 
     } 

    } catch (Exception e) { 
     e.printStackTrace(); 
    } finally { 
     entityManager.close(); 
    } 
} 
private Object getPrimaryKey(Object object) { 
    return entityManagerFactory.getPersistenceUnitUtil().getIdentifier(object); 
} 
+0

はここにパフォーマンスを最適化することが可能とanswer.Isいただきありがとうございますか!それも役に立つでしょう。 –

+0

いいえ、ここではこれ以上の最適化はありません。バッチごとにhibernateとJPAを使用しているので、レコードの存在を確認し、更新/挿入を行う必要がありますので、ここでそのようなことを避けることはできません。 mysqlとのraw接続を使用している場合は、その特定のレコードが存在しない場合に挿入するオプションがあります。 –