-1

I'm writing method to update batch using entity manager(Eclipselink as a provider). One approach I found here Batch updates in JPA (Toplink) and here (JPA - Batch/Bulk Update - What is the better approach?) but I'm not using spring Data JPA. If i use JPQL then entity will not be added to cache(is it right.) I'm using following approach. But it is slower one Any other approach I can use ?

    @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);
}

Thanks in advanced.

Community
  • 1
  • 1
Shatayu Darbhe
  • 797
  • 1
  • 7
  • 13

1 Answers1

0

Here is your modified code,

@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);
}
biology.info
  • 3,500
  • 2
  • 28
  • 39
Hakuna Matata
  • 755
  • 3
  • 13
  • Thank you for answer.Is it possible to optimize performance here ? That will be helpful too. – Shatayu Darbhe Apr 28 '16 at 08:02
  • No. There is no further optimization here. Because you are using hibernate and JPA so for every batch it should verify the record's existence and then need to do update / insert so we can't avoid such things here. If you are using raw connection with mysql then there is an option to insert if that particular record is not there. – Hakuna Matata Apr 28 '16 at 08:22