how to configure transaction manager in spring
I notice that many developers whom will encounter some bad exceptions while trying to integrate spring and hiberante.
Actually I somehow had them because they are very normal situation in progress of integration.
Here I want to clarify this transaction
related problem.
exception
org.hibernate.HibernateException: No Session found for current thread
This is pretty ambiguous because we think Spring
will manage session, but there is something hidden in hibernate.
Hibernate need to explicitly openSession
first in the SessionFactory
to gain session and cache it in CurrentSessionContext
(ThreadLocal
by default) container. You can use getCurrentSession
to get session from ThreadLocal
or other CurrentSessionContext
if it already created from previous open
action.
By my experiment, you will get this No Session found for current thread
exception when you trying to get session without explicitly open
it.
1 |
|
But you will receive Exception if getCurrentSession
without invoking create session first.
1 |
|
After explaining the exception above, you now may know root cause of this problem so as to better understand its scheme.
Now
let’s learn to configure transaction manager.
There are two way of configuring transaction manager in spring integrated with hibernate.
- programmatic
- Declarative
You can easily understand that the programmatic way of configuring transaction manager is to beginTransaction
and commit
manually in Java code, which is cumbersome but is actually ease your worries as everything are under your control. This article will not introduce it at all.
I will not recommend it to you, because Declarative
could still have very good control but much higher productivity and better code style by good modularization.
1. Add Spring transaction manager for Hibernate
Add this bean in spring’s applicationContext.xml
configuration file to enable spring delegate transaction manager functionality.
1 |
|
2. Declare transaction points and transaction configure
The declaration for this could have three ways of configuring this step.
It is recommended to annotate @Transactional
on service layer
since service will handle most of business logic and could guarantee the overall business transactional consistency.
There is another thing to refer, the propagation
of transaction mean to spread from invoker to invokee, rather passing from bilateral method, see examples:
1 |
|
For more please visit spring framework reference.
1. AOP based
AOP based transaction is very clear and simple:
1 |
|
The txAdvice
tells transaction manage how to make transaction propagation or some other transactional related metadata.aop:config
is to create cut point aspect, then delivery this point to transaction manage to make transactional management, after completion of method invocation, AOP will cut a point to let txManager
to commit
or rollback
so as to ensure transactional consistency.
Beware you must configre AOP at the implementation
class rather than interface
.
2. annotation driven
Add snipplet in applicationContext.xml
to enable annotation driven transaction management.
1 |
|
This is all XML that needed for annotation driven configuration, pretty simple.
Then you can add @Transactional
annotation on any method in @Service
implementation class, or just on the service class to enable the whole class to be transactional managed and in same transaction behavior.
Beware that you must put this annotation on implementation class rather than interface
.
Some samples:
1 |
|
3. mixed style
You can also mix these two styles together to make it flexible.
Test
My depiction completed, now have a test, just to throw an RuntimeException
to test data consistency, you will find hibernate DEBUG
tells you that it rollback sucessfully.
Congratulation!