spring transactional nested open session? - spring

If a method of service is marked as #Transactional with propagation nested, and inside it there are many calls to other #Transactional methods, each one of these methods will use its own session? It should represent many connections to db for just one method call no?

It looks like PROPAGATION_REQUIRED is better option for your purpose. From its javadoc:
Support a current transaction; create a new one if none exists.
Refer this link for more details

Related

Spring getCurrentSession() and save sevaral object

Currently, I use openSession(), begin and commit transaction in a method with classic dao and service layers and save/update/delete multiple object in it. If any error exist I am sure that any save/update in this method did not done.
Is it possible to save more than one object in a method called with #Transactional annotation via getCurrentSession() and it is safe if this guarantee that all object in this method saved/updated or any did not done? And if possible how can I use rollback in this method?
Yes you can, with proper transactional semantics.
#Transactional has a property named rollbackFor = TypeOfException.class. By default it rolls back RuntimeException, but you can specify your own or just Exception for any checked exception.
You should have a proper propagation aswell which again you can specify as a property on #Transactional. Note that if you set propagation = REQUIRES_NEW and an existing transaction calls this method, that will rollback for the nested transaction only. What you're trying to achieve, the most common one I think is to specify propagation = REQUIRED - this will not run on its own transaction but proceed on the existing one, which means that on case of failure the whole transaction will rollback.

Not using #Transactional and calling persistence layer methods

I have my services like this annotated with #Transactional
#Transactional
#Service
public class Contact_Service {
....
In my Controller i don't have #Transactional and sometimes i use some persistence layer methods directely to search and persist my object and everything is okey :
#Controller
public class GestionAO {
....
#RequestMapping(...)
public String alerte() {
contact_respository.findOne(...) ;
...
contact_respository.save(...) ;
My question since my controller is not in a transaction will i got some problems ?
Can my object don't get saved in some cases ?
Will i got concurrence problem ?
Looks fine now when you have only one save call. If there are multiple DML or DDL operations executed from the Controller you will lose on not having transaction management. You will lose on the ACID behavior that transactions offer.
The purpose of having #Transactional annotation is to perform multiple database operations in a single transaction. If one operation fails, entire transaction should be roll-backed. Otherwise this can cause data integrity issues.
And the most important thing is to have #Transactional on service layer methods. Because that's one layer who knows unit of work and use cases. In some cases you will have to call multiple DAO layer methods, those all operations are called from service layer and mostly from single method. So it is always better to annotate your service layer methods as #Transactional.
To sum it up, You must have #Transactional annotations on service layer methods.
you should only annotate service with #Transactional. to make sure all of db operations under single transaction, it is recommended to add a new method in service which contains all you db operations, and just call this new method in controller.

Do Spring transactions propagate through new instantiations

I'm working on a bunch of legacy code written by people before me and I'm confused about a particular kind of setup and wonder if this has ever worked to begin with.
There is a managed bean in spring that has a transactional method.
#Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Throwable.class)
public boolean updateDraftAndLivePublicationUsingFastDocumentsOfMySite(List<FastDocumentLite> fastDocumentLites, Long mySiteId) throws Exception { ... }
Now inside that method I find new instantiations calling update methods fe:
boolean firstFeed = new MySiteIdUpdate(publishing, siteDao, siteDomainService).update(siteId, fastDocumentLites.get(0).getMySiteId());
From my understanding on IOC this new class isn't managed by spring , it's just a variable in the bean. Now going further inside the update method you see another service gets called.
#Transactional(propagation=Propagation.REQUIRED, rollbackFor=Throwable.class)
public void activateSubdomainForSite(Long siteId, boolean activationOfSite)
So if there is a transaction open it should be propagated into this service. But here is what I don't get if that MySiteIdUpdate object isn't managed by spring does the first transaction move forward to the activateSubdomainForSite method ?? Or is another transaction being opened here. I looked in the logs and I believe it to be the latter but I rather ask the experts for a second oppinion before I proclame this legacy code to be complete rubbish to the project lead. I'm suffering with a StaleStateException somewhere further down the road and I'm hoping this has anything to do with it.
I think the code is correct, and the second #Transactional should reuse the existing transaction.
Because:
1) Spring Transaction handling is done either by Proxies or by AspectJ advices. If it is done by Proxies then it is required that MySiteIdUpdate invoke an instance that is injected (this is what you did). If you use AspectJ, then it should work anyway.
2) The association Transactions to the code that use is done by the Thread, this mean, as long as you "are" in the thread which started the transaction you can use it. (you do not start an new thread, so it should work)
An other way to explain: It is perfect legal when you have some method in your call hierarchy that does not belong to an spring bean. This should not make the transaction handling fail.

Transactional annotation on whole class + excluding a single method

I have a class with #Transactional annotation (instead of marking it for all of its method).
Although i have a single method inside that class that shouldn't be annotated as #Transactional.
My question is is there an annotation i can put in this method to mark it as "non-transactional"? or should i start marking each single method in this class as "transactional" excluding this method (a lot of work)
thanks.
There are different transaction propagation strategies to use. These exist in the enum Propagation. The ones you might want to use are
/**
* Execute non-transactionally, suspend the current transaction if one exists.
* Analogous to EJB transaction attribute of the same name.
* <p>Note: Actual transaction suspension will not work on out-of-the-box
* on all transaction managers. This in particular applies to JtaTransactionManager,
* which requires the {#code javax.transaction.TransactionManager} to be
* made available it to it (which is server-specific in standard J2EE).
* #see org.springframework.transaction.jta.JtaTransactionManager#setTransactionManager
*/
NOT_SUPPORTED(TransactionDefinition.PROPAGATION_NOT_SUPPORTED),
/**
* Execute non-transactionally, throw an exception if a transaction exists.
* Analogous to EJB transaction attribute of the same name.
*/
NEVER(TransactionDefinition.PROPAGATION_NEVER), // maybe not this one
So annotate the method inside your class with either of these.
#Transactional
public class MyTransactionalClass {
#Transactional(propagation = Propagation.NOT_SUPPORTED)
public void nonTransactionalMethod() {...}
}
You can find all the propagation strategies here.
Sorry to answer a six year old question, but I noticed the accepted answer doesn't actually answer the question. The question was how to have a method behave as though it was not annotated with #Transactional at all. Such a method will take part in a transaction if there is one, or execute non-transactionally if there is not. It will not suspend an existing transaction, or refuse to execute if there is one, one of which would be the result of the accepted answer.
The propagation to use is Propagation.SUPPORTS (in other words annotate the method with #Transactional(propagation = SUPPORTS). This will take part in the transaction if there is one, or execute non-transactionally if not, just like a non-annotated method would.
Not that according to the Javadoc it is not exactly the same as having no #Transactional annotation at all. It says:
Support a current transaction, execute non-transactionally if none exists. Analogous to EJB transaction attribute of the same name.
Note: For transaction managers with transaction synchronization, 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.
The only way to have the method behave exacty as if it was not annotated with #Transactional at all is to do as OP suggests: don't annotate the class, but annotate all the other methods, but for most uses that will not be necessary and using Propagation.SUPPORTS will suffice.

#Transactional Annotation + for a data insertion in a loop

I am using Spring 3, JPA + Hibernate for a CMS application. In that application I have a service class method which is annotated with #Transactional Annotation with rollBack property. Inside that method I am inserting data (ie entity classes) to a table using a loop. For each iteration of the loop entity classes has to be saved to the database. But it is not happening. The commit only happens when the execution of the loop has completed and exits from the method. Then it commits and saves all at once. But I need to read data once it gets inserted into the database before committing in this case. I tried with the ISOLATION LEVEL to read uncommitted but it didn't supported since I am using the default JPADialect. Also tried to add the hibernate implementation of jpaDialect but still it didn't worked. Please help with a workaround for this problem. One more thing, is there any way using propagation required method.
You are right, this is what I stands for in acid. Because the transactions are working in isolation, other transactions cannot see them before they are committed. But playing with isolation levels is a bad practice. I would rather advice you to run each and every iteration in a separate transaction with start and commit inside.
This is a bit tricky in Spring, but here is an example:
public void batch() {
for(...) {
insert(...)
}
}
//necessarily in a different class!
#Transactional
public void insert() {
}
Note that batch() is not annotated with #Transactional and insert() has to be in a different class (Spring service). Too long to comment, but that's life. If you don't like it, you can use TransactionTemplate manually.
remove the transactional annoation on the the method with loop.
In the loop call a separate method to perform the save, make that method transactional
You either need to go with programmatic transactions (Spring's TransactionTemplate or PlatformTransactionManager are the classes to look at, see Spring Doc for programmatic transactions, or you can call another transactional method from within your loop where the transaction is marked with Propagation.REQUIRES_NEW, meaning each call of that method is executed in its own transaction, see here. I think that the second approach requires you to define the REQUIRES_NEW method on a different Spring bean because of the AOP-Proxy. You can also omit the REQUIRES_NEW if the loop is not executed within a transaction.

Resources