I have this requirement:
- Csv Upload (using opencsv)
- Should display if the record is inserted (if it doesn't exist in the db) or updated (if it exists). Eg.: 5 records inserted 2 records updated.
Usually I use repo.saveAll(entityObjList)
to save all the entries.
Since I have to keep track of number of updates and inserts, I came up with using the repo.save(entityObj)
method inside the for loop which is not greatly appreciated.
Is there any other way to approach this problem ? Any suggestion is welcome.
3 Answers 3
If the count of the inserts/updates is the only thing you need, quick (and possibly dirty) solution might be to keep using saveAll
method and selecting the count of the entities in the database before and after the saveAll
call -- all wrapped in a transaction of course. Knowing the size of the collection passed to saveAll
you can calculate how many entities were created and how many were updated in the database.
Since the Ids of the entities are numeric and generated by the database on insert, loop over all of the entities. If the Id of an entity is 0 or null, then it will be an INSERT
. If the Id of an entity is greater than zero (or what ever the minimum number of the sequence is) then it will be an UPDATE
.
You would loop over the entities to be saved and tally up in the inserts and updates, then call the saveAll
method on the repository, where you can get the performance boost over calling save
for each entity individually.
Summing the inserts and updates might be better off in a service layer or class representing a use case, rather than the repository. The additional loop to detect the inserts and updates will add overhead, but you should be fine performance-wise until you reach the 1,000s of entities.
Even then, measure the performance to see if the decrease is small enough to make this feature worthwhile.
From org.springframework.data.jpa.repository.support.SimpleJpaRepository
/*
* (non-Javadoc)
* @see org.springframework.data.repository.CrudRepository#save(java.lang.Object)
*/
@Transactional
public <S extends T> S save(S entity) {
if (entityInformation.isNew(entity)) {
em.persist(entity);
return entity;
} else {
return em.merge(entity);
}
}
//...
@Transactional
public <S extends T> List<S> save(Iterable<S> entities) {
List<S> result = new ArrayList<S>();
if (entities == null) {
return result;
}
for (S entity : entities) {
result.add(save(entity));
}
return result;
}
Basically, you can mimic what save(Iterable)
does. Use the annotation @Transactional in your repository method and choose the propagation strategy that best works for you. REQUIRED
should be enough.
Explore related questions
See similar questions with these tags.
saveAll
method so it returns that number?JpaRepository.save()
inside the for loop because of this. TheJpaRepository.saveAll()
seems to return the last saved object. It is not my implementation of the same.saveAll
from the defaultSimpleJpaRepository
... just does a for loop and callssave
on every entity therein. So doing a for loop and saving each thing... is exactly the same performance as saveAll.