Spring Data JPA saveAll/Save method as batch insert - spring

I have noticed the behaviour of the save method performing the insert as a batch when setting spring.jpa.properties.hibernate.order_inserts=true. The saveAll is indeed doing the batch insert. But what I found strange is that the save method is doing batch as well.
Is that normal?
Thanks.

Yes, that is normal. In the end, batching is a Hibernate feature and Spring just calls persist/merge on the EntityManager. Hibernate figures out behind the scenes how it can do batching.

Related

Exception Handling in Spring Boot + Schedulers + Spring Data JPA + Oracle

I'm trying to figure out what all the exception's can be handled/caught and process for some other means like DB insert into a table?
Majorly, there is no controller or API is being exposed. Instead only schedulers read the data from Oracle DB table by JPA Queries (i.e., Not Native Queries) and used Pessimistic WRITE Locking with Query hints as timeout specified. Later, processed data will be sent to external system as byte array.
I encountered few exceptions like JPASystemException, LocktimeoutException and others but somehow, I couldn't catch them.
Any ideas?
You could use AOP and define pointcuts and advices for all methods that access the db and might throw an exception. Spring offers advices such as AfterThrowing and Around which can hold your error handling logic.

How to rollback all committed transactions if any error encountered while reading csv file records using hibernate

I have a CSV file which contains around 10Mb data which I use to populate my entire database. Suppose If I encountered an error while reading a record from CSV file I need to abort all my committed transactions ?
In my project, I have a threshold like if 5% of my records in CSV go wrong I will abort all committed transactions associated with that CSV file else if less than 5% I will only take out that record a keep in a separate file.
pl let me know how to abort all committed transactions(involves 15+ DAO classes) in hibernate.
Thanks for the suggestions.
Once a transaction is comitted it can't be reversed. Not in Hibernate, not in any database!
To keep your operations reversible you need to keep them in the same single, not yet comitted transaction and if any (by default runtime) exception arises it will automatically be rollbacked and all changes reversed.
You tagged your question as Spring, in Spring you can use #Transactional annotation over the method, and all changes in that method will be reversed in case of any transaction, including other methods called from that method.
more here https://www.baeldung.com/transaction-configuration-with-jpa-and-spring
also there is any example here https://javamondays.com/spring-transactions-explained/

Can a commit be reverted in Javers?

I have a scenario where in case a subsequent operation fails, a commit or a shallow delete might need to be reverted. This would be particularly useful in scenarios involving Mongo where there is no atomicity available across collections. Is this possible with Javers?
There is no 'rollback' option for now. It can be implemented in the future but there could be some limitations.
You could annotate your method with #Transactional annotation and if an exception occurs the database updates that occurred within that method would rollback which should include the Javers tables.
https://www.logicbig.com/tutorials/spring-framework/spring-data-access-with-jdbc/transactional-roll-back.html
Alternatively, you could use Spring AOP to perform a custom rollback and then delete the committed records manually.
How to call a custom rollback method in Spring Transaction Management?
Hope one of these options helps you.
If you need to travel back in time, instead of using Javers, you should redesign your database using functional programming idea called "persistent data structures". At the core of it is that you should never modify any existing data, you should always create new versions of existing entities.
You can read about persistent data structures for example here:
https://medium.com/#arpitbhayani/copy-on-write-semantics-9538bbeb9f86
https://medium.com/#mmdGhanbari/persisting-a-persistent-data-structure-3f4cfd46036

Is a Spring Data JPA #Query dynamic or named?

JPA #NamedQuery is translated to SQL only once when application is deployed and generated SQL is cached.
EntityManager.createQuery translates query every time our method is called.
What Spring-data-jpa is doing with query defined in #Query annotation? Is it translated to SQL once during deployment (like NamedQuery) or translated every time (like dynamic query) ?
Spring Data JPA calls EntityManager.createQuery(…) for every invocation of a query method annotated with #Query. The reason for that is quite simple: the Query instances returned by the EntityManager are not thread-safe and actually stateful as they contain bound parameter information.
That said, most of the JPA persistence provider perform some kind of text-based query caching anyway so that they basically build the actual SQL query once for a certain JPQL query and reuse the former on subsequent invocations.
As an interesting side note, when we started building the support for #Query in 2008 we looked into possibilities to rather register the manually declared queries as named queries with JPA. Unfortunately there wasn't - and up until today - there's no way to manually register a named query programmatically via the JPA.

Getting Exception when trying to update record second time in hibernate

We keep user object in session. When we update it first time ( using entityManager.merge( ent )) it works fine; but second time I get following exception:
org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [com.kids.domain.Child#22]
at org.hibernate.event.internal.DefaultMergeEventListener.entityIsDetached(DefaultMergeEventListener.java:492)
at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:256)
at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:86)
at org.hibernate.internal.SessionImpl.fireMerge(SessionImpl.java:781)
at org.hibernate.internal.SessionImpl.merge(SessionImpl.java:766)
I am using spring with hibernate & jpa. Spring is injecting EntityManager in DAO. I do understand that if I would do a fresh find() everytime then make all the changes on that object and then merge().. it will work fine.. but in my case I cannot do that.
I also checked that the hashcode of EntityManager used is same both time; i.e same EntityManager instance is getting used both time then why it gives this exception when trying to update a record second time
Any help would be highly appreciated.
I tried lots of things but nothing worked. Even on internet there was no solution. Finally, when I removed version from my entities ( i.e. remove OptimisticLockException support provided by hibernate ).. everything started working fine. Probably , I will try to handle OLE myself.
When you call merge method in the current transaction, hibernate will copy the state of the given object onto the persistent object with the same identifier and returns new manageable entity. You need to work on the manageable entity which is returned by the merge in subsequent operations because this entity has new version than in DB.

Resources