My entity has both autogenerated primary key (id) and business key (namespace). I need to update the record by replacing the old one. So, I'm searching it by business key, delete it and save a new entity. This works if each operation in it's own transaction. But once I put all of them in the same transaction, by the time save() is executed, delete() wasn't executed yet, so I get a constraint violation.
transactionTemplate.execute(status -> {
MyEntity oldEntity = repository.findByNamespace(namespace);
if (oldEntity != null) {
repository.delete(oldEntity);
}
repository.save(newEntity);
return null;
});
I actually managed to bypass it by adding
repository.flush();
But I don't really get why do I need this flush().
The solution is to use @javax. persistence. Version on a new versionNumber column in all the tables. If you have a parent and child table then use @Version column in all the entity classes.
Crud Repository doesn't provide methods for implementing pagination and sorting. JpaRepository ties your repositories to the JPA persistence technology so it should be avoided. We should use CrudRepository or PagingAndSortingRepository depending on whether you need sorting and paging or not.
Method Summary Deletes the given entities in a batch which means it will create a single query. Deprecated.
Save and saveAndFlush both can be used for saving entities. They both are both belong to the Spring data library. save may or may not write your changes to the DB straight away. When we call saveAndFlush system are enforcing the synchronization of your model state with the DB.
Because repository.flush() flushes the changes to the database by calling EntityManager.flush(). So when you flush the changes after delete(), sql gets executed and the following save will have no problems.
If you don't call flush it is up to persistence provider to determine when to flush the changes with transaction commit time being the deadline. Also providers don't flush changes in any particular order, so it may happen that sometimes your operation succeeds and sometimes it doesn't. Usually, providers wait until the commit time flush, but you can influence that by setting a flush mode:
for entitymanager
EntityManager.setFlushMode(FlushModeType type);
or for query
Query.setFlushMode(FlushModeType type);
There is an equivalent setting in Spring data JPA also, I'm sure, but I don't exactly know which one it is.
Note however, that immediately flushing the changes reduces the performance, so you should be careful when using it. In your particular case it is better to update the entity then it is to delete it and then persist the new one with the same business key.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With