Spring disable transactions for a single class method - spring

In my Spring application, I have a class annotated with org.springframework.transaction.annotation.Transactional annotation.
Is it possible to discard transactions for a specific single method of this class without removing #Transactional from class level declarations? If so, please show an example

According to Transactional documentation:
public #interface Transactional
Describes a transaction attribute on an individual method or on a class.
So additionally to the class-level annotation just define the correct attribute at your method to disable the default transaction handling.
example:
#Transactional(propagation=Propagation.NEVER)
public long notInTransaction(AnythingData anythingData) throws Exception {
//JDBC code...
}
Will throw an exception if this method is called inside an active transaction. Whereas Propagation.NOT_SUPPORTED will "suspend" the current transaction and make sure that the method is called non transactional.

Related

Spring non-transactional nested method inside #transactional is the same as #transactional propagation = support

i) Are there any difference, 1) if I call a non-transactional method from inside #transactional AND 2) call call a #transactional with propagation level = support from the same #transactional method?
ii) Are there any difference if answer for the question i) if it's the same bean or different?
Thanks
i) Are there any difference,
1) if I call a non-transactional method from inside #transactional AND
If you call a method within a transaction, without any settings, the transaction will span to the calling method.
2) call call a #transactional with propagation level = support from the same #transactional method?
Propagation.SUPPORTS annotated method will be executed in the current transaction, just like if you call a non-transactional method.
The only different between setting #Transactional(propagation = Propagation.SUPPORTS) and not setting #Transactional is noted in javadoc:
Note: For transaction managers with transaction synchronization, PROPAGATION_SUPPORTS is slightly different from no transaction at all, as it defines a transaction scope that synchronization will apply for. As a consequence, the same resources (JDBC Connection, Hibernate Session, etc) will be shared for the entire specified scope. Note that this depends on the actual synchronization configuration of the transaction manager.
ii) Are there any difference if answer for the question i) if it's the same bean or different?
Spring #Transactional annotation default using AOP proxy.
When you calling methodB from methodA within the same class, the AOP proxy will not be activated for the methodB (i.e #Transactional annotation in methodB is completely ignored).
When you calling from different class, then the behavior is same as i)

Cache Evict is not working

in my project, I am using a #Cacheable annotation ia a service method that returns results of calculation involving books and some marks, and i want to Evict Caching in a #Controller class method that adds a new book to the database, because this new one will be necessary to a new calculation.
Service class:
#Cacheable("metas")
public ... calculate(){return calculation;}
Controller class:
#RequestMapping
#CacheEvict(value="metas", allEntries=true)
public void addNewBook();
Why it is not working?
Most likely you have #EnableCaching in the root application context. This wont have an effect on the child DispatcherServlet application context. The #CacheEvict annotation on your controller wont be processed. Spring uses BeanPostProcessor to weave caching behaviour at runtime through the use of proxies. BeanPostProcessors are scoped per application context.
Move the addNewBook method definition and the cache metadata to your service class and call that method from the controller

Where can I use #Transactional

Can someone explain me why this will work:
#Transactional
#Test
public void test() {
save();
}
public void save() {
Scenario scenar = new Scenario();
sessionFactory.getCurrentSession().save(scenar);
}
And this won't, because it won't find a transaction:
#Test
public void test() {
save();
}
#Transactional
public void save() {
Scenario scenar = new Scenario();
sessionFactory.getCurrentSession().save(scenar);
}
Thank you!
Spring #Transactional annotation works using Spring AOP. This means, that when a bean that contains a method with that annotation is injected as a dependency for a different bean, it gets wrapped in a proxy. This proxy has the same interface as the bean, but performs additional actions before a method is invoked (wrapping it in a transaction in this case). You can think of it as a sort of a decorator. You can even see the proxy being invoked when you debug your application.
Now, when the method that you annotate with #Transactional is called from the same class, there is no (at least, no easy) way to inject the proxy. There just isn't a way to replace the object referenced by the "this" keyword in Java.
More reading on Spring AOP proxies.
As you have a method annotated as #Test I assume this is part of a Junit Test class.
Spring developpers know that test methods usually do not implement interfaces, and as such cannot support JDK proxying. So they specially support #Transactional annotation on a #Test method. The doc says :
Enabling and disabling transactions
Annotating a test method with #Transactional causes the test to be run within a transaction that will, by default, be automatically rolled back after completion of the test. If a test class is annotated with #Transactional, each test method within that class hierarchy will be run within a transaction. Test methods that are not annotated with #Transactional (at the class or method level) will not be run within a transaction. Furthermore, tests that are annotated with #Transactional but have the propagation type set to NOT_SUPPORTED will not be run within a transaction.

Intercepting transaction multiple times

How bad is it intercepting transaction multiple times?
For example one service method marked #Transactional calls another service method which also is marked with #Transactional annotation and so on? Which problems may it cause?
There is the propagation attribute at the #Transactional annotation. It is responsible for setting the expected behavior when a (second) method with #Transactional is invoked.
#See Java Doc: Transactional.propagation
#See Java Doc: Propagation

In Spring 3.2, should we use #Transactional annotation for db activities?

I use spring 3.2 and Hibernate 4 in my project. When i query table i get a "No Session found for current thread" message. I try to use #Transactional annotation(it get success) but i don't want to put #Transactional to every service implementation.
Is there an another way?
In other words "How can i do a simple "insert" operation without using #Transaction?"
Thx...
You should not have #Transactional on you DAO methods, in fact you should never be accessing your DAO methods directly, you should be using an #Service. A service will use zero or more DAO classes to perform operations, only after all operations are completed will the transaction be committed.
#Repository
public class CustomerDao() {
// dao methods here, they are not transactional but will be run within a sevice transaction
}
#Service
#Transactional
public class CustomerService() {
private final CustomerDao customerDao;
#Autowired
public CustomerService(CustomerDao customerDao) {
this.customerDao = customerDao;
}
//service methods here (they are all transactional because we have annotated the class)
}
#Transactional is used for making a java code call in transaction so that in case any exception occurred during the process then all database changes will be rolled back. In ideal scenario every service which you think should be independent should have #Transactional annotation. Hibernate also want each database calls in transaction thats why they have implemented in such a way that Transaction will be required for each database query to be successful. I am not sure why you wanted your service to be out of transaction still they would like to fire database calls.

Resources