Is there any way to persist some data in database after an exception occurs in ItemWriter in spring batch? - spring

I want to persist some data after an exception occurs in ItemWriter step. But if I am not incorrect, in this case a rollback would happen and so this persisting logic won't work.Is there any way to achieve this?
Right now, I am implementing itemWriteListener and all the persisting logic is written inside onWriteError method. This logic only concerns to change state of some entities to error.

You'll want to use a separate connection that does not participate in the transaction. For example, inject a DataSource into your listener and construct your own JdbcTemplate with an independent connection. By doing that, the writes should not be rolled back.

If you mark the onWriteError method with
#Transactional(propagation = Propagation.REQUIRES_NEW)
...would this work as well?

Related

Spring jpa: Do I need to add #Transactional annotation on retrieval queries

I am using EntityManger for the retrieval queries in my spring boot application. An example snippet is given below.
#Repository
public class EntityManagerUtil {
#PersistenceContext
private EntityManager entityManager;
public List<Employee> getAll(){
// Use entityManager here
}
}
I need some clarity on the below questions.
a. Is EntityManger will be created for every call (or) will it be a singleton? (I tried printing entityManager, it is returning the same object for all the calls)
b. Is this approach leads to any connection leaks?
c. Do I need to put #Transactional annotation on reading operations?
I am using spring boot version 2.0.3-release
a) See M Deinum's comments about the injected EntityManager being a proxy. The normal situation for JPA is to have an EntityManager tied to each thread, Spring sets this up for you and provides a proxy to delegate to the actual EntityManager. So this arrangement is safe.
b) Connection leaks happen when you don't return a database connection to the pool. Spring takes care of providing a connection and cleaning up resources so in the normal course of things you shouldn't get connection leaks. If you ignore the facilities Spring gives you like JdbcTemplate and insist on writing your own JDBC code, then you can cause resources to leak. If your code tries to use an EntityManager intended for another thread you will get an exception, it will not fail silently, and it will not (in itself) cause a connection leak.
c) You are using an RDBMS so you will have a transaction.
Apparently some people think transactions are optional, but they really aren't. If you don't specify them then Spring will wrap each operation in its own transaction. Not only are you just better off in general being explicit about this, but you can mark the transaction as readonly, which lets Spring perform some optimizations, see Oliver Drotbohm's answer for details. So maybe you can get by without it for some cases (such as, each http request results in only one database operation), but it is in your interest to use it.

How to deal with Spring hibernate no lock aquired exception inside a transaction

I have applied #Transactional in my interface, and inside my serviceImpl, the corresponding method is calling some other methods, one method is reading, another method is writing. Although I have anotated as Transactional, when I am giving concurrent request, my insert method is throwing org.hibernate.exception.LockAcquisitionException: error.
Another problem is, this insert method is a shared method and it performs the insert method like Dao.save(obj) . Dao.save() is a generic method So i can not do anything here. I have to apply something on interface to avoid no lock aquired exception.
Is it possible to tell wait untill lock is aquired? Or retry if transaction is failed? Or lock all the tables until the transaction is completed so that another request can not access the relevent resources?
My hibernate version is 3.x, And database is mysql 5.6
The best way to do this is,
Mark your methods transactional
In your mysql database settings set the transaction isolation level as SERIALIZABLE

Can the rollback of Spring declarative transaction be postponed

Question:
Is there a way to allow Spring declarative transaction to postpone the rollback on exception ?
Use case:
I have to process several entities together in a single transaction.
The result of processing a single entity are a few new records in the DB and a few updates to existing ones.
If processing of any of those entities results in an exception, the transaction needs to be rolled back. So, all entities must be processed successfully in order for transaction to be committed.
The twist: I want to detect all the entities for which processing ends up with exception in one go. I do not want to run processing once, fail on entity No5, fix the issues on entity No5, and then run processing again only to be greeted by an exception on entity No7.
So, what I am trying to achieve is to gather all the errors on entities that are in a faulty state and notify someone to fix them. Due to this, I want the transaction that encapsulates all entities processing to carry on till the last entity and only then I want a rollback to happen.
What I tried so far:
Using propagation = NESTED like this:
#Transactional
void processAllEntities() {
entities = fetchEntities();
for (entity : entities) {
processSingleEntity();
}
}
#Transactional(propagation = NESTED)
void processSingleEntity(entity) {
do stuff;
}
Please note that methods above are in different #Component annotated classes and processAllEntities() is invoked from a third class.
This failed because JpaDialect does not support savepoints.
I tried to switch to DataSourceTransactionManager as suggested in the javadoc of Propagation.NESTED but then nothing is persisted since this transaction manager seems to be JPA unaware and my whole model is mapped with JPA annotations and I'm using spring-data-jpa for persistence.
Any ideas and feedback are welcome. Thanks.

#Transactional with 1 save statement

Does it make sense mark with spring's #Transactional a method with a single save sentence?
For example:
// does it make sense mark it with #Transactional if it only has 1 save sentence?
#Transactional
public void saveMethod() {
user.save()
}
If you´re using Spring data interface, you dont need use #transactional annotation. Only in case that you want to provide two execution against the database and you want to share the transaction, so then rollback of both actions can be made.
Anyway it is always better use #transactional even as read-only for get queries(setting the FlushMode to MANUAL to let persistence providers potentially skip dirty checks when closing the EntityManager), so I would suggest put the #transactional as Service layer and read-only for get queries.
Yes because any "modifications" on the database requires a transaction (to commit the changes). You might think otherwise because of auto-commit, but in the end, there is still a transaction there somewhere.
But it is always a good thing to explicitly define the boundaries of your transaction (when transaction is started and when it is committed).

Spring jdbcTemplate Rollback for multiple database operations

I have a program that uses handler, businessObject and DAO for program execution. Control starts from handler to businessObject and finally to DAO for Database operations.
For example my program does 3 operations: insertEmployee(), updateEmployee() and deleteEmployee() every method being called one after the other from handler. once insertEmployee() called control get back to handler then it calls updateEmployee() again control back to handler then it calls deleteEmployee().
Problem Statement: If my first two methods in dao are successful and control is back to handler and next method it request to dao is deleteEmployee(). Meanwhile it faces some kind of exception in deleteEmployee(). It should be able to rollback the earlier insertEmployee() and updateEmployee() operation also. It should not rollback only deleteEmployee(). It should behave as this program never ran in system.
Can any one point me how to achieve this in spring jdbcTemplate Transaction management.
You should check about transaction propagation, in special: PROPAGATION_REQUIRED.
More info:
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/transaction.html#tx-propagation

Resources