Spring Declarative transaction management with hibernate using #Transactional - spring

My requirement is to save data in 5 tables through 5 methods .
These 5 methods are wrapped under single parent method which is annotated with #Transactional.
Am calling this parent method 100 times in a loop.
Constraints are
Transaction has to be rolled back even if one method fails in one iteration.(i.e 5 methods has to be saved without exception) and the flow should continue for next iteration.
One iteration fail should not rollback all the other iterations. I.,e In 100 iterations if 5th iteration fails and all the other iterations are succeeded, then all the 99 iteration's operations should get committed.
It is OK if transaction is committed after successfully executing all the 5 methods in one iteration.
Issue is
If, 5th iteration is failed, then in next iteration, old values are showing in the entity.
I have used session.clear() method in catch block to avoid that. is that correct? But the issue is,
even after successful insertion of five methods in next iteration, the transaction is getting rolled-back. And all the previous 4 iteration's data state in session is getting cleared.
am using Spring 3.2, Hibernate3, HibernateTransactionManager

I forgot to write the caller method and calling method in different beans. Hence it is getting rolled back. Spring Transaction uses AOP. A proxy is created for the methods which are annotated with #Transactional. This bean method should be called from another bean, which I got form the Spring documentation

You want your iterations succeed or fail independently one from another. You want a failure in any of the 5 steps of the individual iteration to fail entire iteration and to roll back the corresponding transaction.
It is clear that you want to have transaction boundary at the level of the service call that corresponds to a single iteration. Now, the rule of the thumb is to allocate a Hibernate session per transaction. So, a Hibernate session should be created at the beginning of each iteration and be disposed of at the end. That would prevent random junk, like entites that failed to be persisted to the database in the previous trnsactions, from showing up in the Hibernate session.
Hope this helps.

Have a look into propagation levels of spring transactions here and choose whatever best suits your requirements. An example which does what you need is as follow (you may mark myService as #Transactional as well) but you might like to have a look at other levels.
public void myService() {
// call myTaskCaller as many times as you like
}
#Transactional(propagation=Propagation.REQUIRES_NEW)
public void myTaskCaller() {
task1();
task2();
task3();
task4();
task5();
}
private void task1(){}
private void task2(){}
private void task3(){}
private void task4(){}
private void task5(){}

Related

use aspectj to retry deadlocked transactions in spring boot

I created a deadlock situation by having 2 functions lock 2 rows in a mysql table in opposite orders. I have #Transactional on both functions. I also have an aspectj aspect on both functions that retries the failed one at most 2 more times.
After the deadlock, one thread succeeds and one fails. The failed one retries. So far so good. However, there are 2 problems after this point.
When the failed function was retried a second time, it reads the 2 rows again. However, the value for the first one is old and the second one is new.
At the end, the transaction fails because the transaction was already marked for rollback. So the #Transactional proxy is around the retry proxy. Is there a way to reverse the order? I tried to have the retry proxy inherit Ordered and set the order to Ordered.HIGHEST_VALUE and Ordered.LOWEST_VALUE but neither worked.
I tried spring retry and it worked like a charm. Still looking into how it does it magic though.
I basically did this:
add dependency on org.springframework.retry spring-retry
add #EnableRetry to application
add #Retryable(maxAttempts = 3, backoff = #Backoff(delay = 2000)) above
#Transactional annotated functions.
This one has the more direct answer:
Intercepting #Transactional After Optimistic Lock for Asynchronous Calls in Restful App
Just added #Order(1) below the aspect.
Turned out the key was to use 1 as the order. I tried the Ordered interface again just like in the problem description. This time using 1 and it worked just the same as the Order annotation is just a shortcut to the interface.

Why does Hibernate not support nested transactions outside of Spring?

I am using Hibernate4 but not Spring. In the application I am developing I want to log a record of every Add, Update, Delete to a separate log table. As it stands at the moment my code does two transactions in sequence, and it works, but I really want to wrap them up into one transaction.
I know Hibernate does not support nested transactions, only in conjunction with Spring framework. I´ve read about savepoints, but they´re not quite the same thing.
Nothing in the standards regarding JPA and JTA specification has support for nested transactions.
What you most likely mean with support by spring is #Transactional annotations on multiple methods in a call hierarchie. What spring does in that situation is to check is there an ongoing transaction if not start a new one.
You might think that the following situation is a nested transaction.
#Transactional
public void method1(){
method2(); // method in another class
}
#Transactional(propagation=REQUIRES_NEW)
public void method2(){
// do something
}
What happens in realitiy is simplified the following. The type of transactionManager1 and transactionManager2 is javax.transaction.TransactionManager
// call of method1 intercepted by spring
transactionManager1.begin();
// invocation of method1
// call of method 2 intercepted by spring (requires new detected)
transactionManager1.suspend();
transactionManager2.begin();
// invocation of method2
// method2 finished
transactionManager2.commit();
transactionManager1.resume();
// method1 finished
transactionManager1.commit();
In words the one transaction is basically on pause. It is important to understand this. Since the transaction of transactionManager2 might not see changes of transactionManager1 depending on the transaction isolation level.
Maybe a little background why I know this. I've written a prototype of distributed transaction management system, allowing to transparently executed methods in a cloud environment (one method gets executed on instance, the next method might be executed somewhere else).

#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).

Using Spring #Transactional processiong only 8 threads parallelly

We are using Jetty+Spring. My WebService HostService receives N requests in parallel (Logged the time as soon as request arrived to my webservice) but when tried calling Transactional add method, something similar to below snippet
#Component
#Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class ClassA {
#Transactional
public Host add(Host host) {
//logging time
Thread.sleep(100);
}
}
Now From code service I made the call to ClassA's add method, and logged the time, only 8 out of 100 request are reaching here at a time, and then when one finishes other starts.
I have already tries removing Thread.sleep with actual webservice call and a local process call, that doesn't help. But when I remove #Transactional, all requests comes at the same time to the add method, so problem is with #Transactional.
I want to understand
how #Transactional actually works, and why it limits to 8 calls in a batch, can I change this batch to some higher number.
All my classes are of scope prototype, so on what its trying to grab the lock on?
What should I do, to process all the requests in parallel, as my app in not db dependent it just calling other webservices(3), I don't need any lock, I just need the thread level lock, so that I can rollback if one of the webservice fails.

spring scope for transaction

I'm a new Spring user.
I have a question about scope and transaction.
For example, there's a service:
<bean id="bankInDaoService" class="service.dao.impl.UserDaoServiceImpl">
Let's say there are 2 people who want to bank-in at the same time.
And I already put #Transactional above for Hibernate transaction the method for bank-in purpose.
My questions are:
Since default Spring scope is singleton. Will these 2 people share the same values. (person 1 bank-in 500, person 2 bank-in 500)?
Will the #Transactional be effective? I mean let the first person finishes bank-in, and then person 2.
I'll be really thankful for your help.
You have wrongly understood the useage of #Transactional annotation.
#Transactional annotation is used in case where you want to get all or none of your transactions to be successful. If any of the transaction fails then other successful transaction will be rolled back. It is not for synchronisation.
If you have registration page where you take input for 10 fields and 5 are for table user and 5 are for table company and you are inseting both records from a single service function. At that time you should use #Transactional annotation. If insertion is successful in user table and fails in company table then the user table record will be rolled back.
Hope this helps you. Cheers.
You are correct that by default Spring beans are singletons. But this won't be a problem unless your implementation modifies some internal state on each invocation (which would be rather odd - typically a service method will just work with the parameters it's been given).
As I just alluded to, each service method invocation will have its own parameters; i.e.:
deposit(person1_ID, 500)
deposit(person2_ID, 750)
As you've said "at the same time" we can safely assume we have a multi-threaded server that is handling both these people simultaneously, one per thread. Method parameters are placed on the stack for any given thread - so as far as your service is concerned, there is absolutely no connection/chance of corruption between the two people's deposits.
Now turning to the #Transactional annotation: Spring uses "aspects" to implement this behaviour, and again these will be applied separately to each thread of execution, and are independent.
If you're looking for #Transactional to enforce some kind of ordering (for example, you want person2 to withdraw the exact amount person1 deposited) then you need to write a new method that performs both operations in sequence within the one #Transactional scope.

Resources