Its you readers who post comments on my blog often induce me to post more information and additional write ups here!I sincerely thank you for that induction you create in me! Based on the information requested, I thought of posting an article here that would help many of you (like me) who end up with the very famous "org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here".
If you are looking at the procedure to incorporate the TxManager in your spring application by making use of @Transactional annotation along with org.springframework.orm.hibernate3.HibernateTransactionManager and , here is the right information that you can make use of! This would not only help you to get out of 'org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here' exception but would also help you in understanding the rudiments involved with the transaction very easily.
Here are the basic steps that you can make use of. Let us say that you have an applicationContect.xml(This is the application context that is loaded by the contextLoaderListener/contextLoaderServlet of your application). Let us say that you have a webdispatcherservlet's webapplication context named as application-servlet.xml.
In this case, please follow the steps given below to incorporate the transactions with ease. In my opinion, it is always recommended that you have your service layer transactional . So i intend introducing the @Transactional annotations at the services in the following example!
If you find the information pretty helpful, I would really be happy if you would keep me posted via the comments form displayed under this article! If you had wanted some other information related to the same topic, I would suggest you to drop a note to me using the comments form for that would help me in getting back to you with the details you are in need of!
If you are looking at the procedure to incorporate the TxManager in your spring application by making use of @Transactional annotation along with org.springframework.orm.hibernate3.HibernateTransactionManager and , here is the right information that you can make use of! This would not only help you to get out of 'org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here' exception but would also help you in understanding the rudiments involved with the transaction very easily.
Here are the basic steps that you can make use of. Let us say that you have an applicationContect.xml(This is the application context that is loaded by the contextLoaderListener/contextLoaderServlet of your application). Let us say that you have a webdispatcherservlet's webapplication context named as application-servlet.xml.
In this case, please follow the steps given below to incorporate the transactions with ease. In my opinion, it is always recommended that you have your service layer transactional . So i intend introducing the @Transactional annotations at the services in the following example!
- First and foremost, define the TxManager bean within the applicationContext.xml as shown below. Remember that this context is the place where you should define the component scan for the services and daos present within your application.
- Note that if you define the bean id of your TxManager as transactionManager, the tx:annotation driven tag can be as given below. It literally means that you need not define the name of your transaction manager in the tx:annotation-driven tag. If you have this bean's id as something else other than "transactionManager", you need to have the the additional attribute "transaction-manager" to the tx:annotation-driven tag.
- Next,define the xmlns for the tx tag as given below in the same applicationContext.xml
- Further, you need to add the schema location for the Tx tag as shown below in the same applicationContext.xml
- Next, go to your daoImpl file say sampleDaoImpl.java and define the sessionFactory as shown below
- Remember that you have to use the sessionFactory injected in your daoimpl as shown below
- Next, go to your service impl layer. Let us say that you have your service implementation file named as SampleServiceImpl.java. Here, you will have to introduce the @Transactional annotations. Be careful and ensure that you make the transaction read only for the find and get queries while you can make the transaction writeable in methods that updates, saves or deletes the objects in db as follows. Here, you can make the @Transactional annotation at class level as read only. When you have an update method that writes to the db, you can annotate that method with @Transactional(readOnly=false) for this would override the class level annotation incorporated as readonly!
- That is it!!!Your application would have included the TxManager successfully! Your db calls would be then managed by the Spring defined TxManager without any problems from here!
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="defaultSessionFactory" /> </bean> <tx:annotation-driven transaction-manager="transactionManager" />
<tx:annotation-driven /><br />
xmlns:tx="http://www.springframework.org/schema/tx"<br />
http://www.springframework.org/schema/tx <br />http://www.springframework.org/schema/tx/spring-tx-3.0.xsd<br />
@Repository("SampleDAO")<br />public class SampleDaoImpl implements SampleDao {<br /><br /> @Autowired<br /> @Qualifier("appSessionFactory")<br /> private SessionFactory sessionFactory;<br />
sessionFactory.getCurrentSession().saveOrUpdate(hibernateObject);<br />or
sessionFactory.getCurrentSession().createSQLQuery("<your query here>")<br />
@Service("sampleServiceImpl")<br />@Transactional(readOnly = true)<br />public class SampleServiceImpl implements SampleService {<br />@Autowired<br />@Qualifier("sampleDAO")<br />private SampleDAO sampleDAO;<br />public sampleObject getObject(int id)<br />{<br />return sampleDao.getObject(id);<br />}<br />@Transactional(readOnly = false)<br />public void update(SampleObject sampleObj) <br />{<br />sampleDAO.saveOrUpdate(sampleObj);<br />}<br />}<br />
If you find the information pretty helpful, I would really be happy if you would keep me posted via the comments form displayed under this article! If you had wanted some other information related to the same topic, I would suggest you to drop a note to me using the comments form for that would help me in getting back to you with the details you are in need of!
It's awesome, you are really helpful. After reading this article, I know I am on the right track. And finally find two silly bugs of my application. My application has similar design with the one your introduce, having Entities, DAO layer, service layer and controller layer. Service layer handling the transaction service which provided by Spring annotation. Controller will only call the services in service layer.
ReplyDeleteHere are the two bugs I found in my codes:
1. I made a silly mistake that let application get the hibernate current session when the application startup.
In the class "GenericDAOImpl":
Before:
protected Session session;
@Autowired
public void setSession(SessionFactory sessionFactory) {
session = sessionFactory.getCurrentSession();
}
After:
@Autowired
private SessionFactory sessionFactory;
public Session getSession() {
return sessionFactory.getCurrentSession();
}
2. I added the tag in both application-context.xml and XXX-servlet.xml files. And obviously, Spring use DispatcherServlet one.
Hi Rico,
ReplyDeleteYet another pointer to you from the recent comment that you have posted. This is regarding the 2 points that you have modified.
Regarding the first point, I understand that you have autowired the sessionFactory instead of the session as such!That should be fine
But regarding the second pointer, I have a second thought. Actually the tag <tx: annotation -driven) should not be inserted in both the config files(appplicationContext and xxx-servlet.xml) - It should be moved to the applicationContext.xml which in turn gets loaded into the application by the contextLoaderListened. Its better that you dont introduce the txManager via the xxx-servlet.xml which is referred to as the webapplicationcontext of your application xxx.
Let me know if you need more explanation on this!
Thanks, you saved me a lot of time...
ReplyDeleteHey akash, Thanks for letting me know about it!
ReplyDeleteGreat post! I missed
ReplyDeletexmlns:tx="http://www.springframework.org/schema/tx"
in my config file. Thanks for help!
Thanks a lot man... It will be really great if u could explain the attributes of the Transactional annotation with examples.. mail me when u r free... softwarevasanth@gmail.com
ReplyDeleteGreat post..
ReplyDeleteIt helped me fix my problem but..
I had error NoSuchBeanDefinationException for hibernateTransactionManager
and in
Then I changed the id to "transactionManager" and remove transaction-manager property from tx:annotation element.
It started working.
Then I changed it back to what it was and it is still working.
Thanks any way
Thanx by zillions.
ReplyDelete