Announcement Announcement Module
Collapse
No announcement yet.
Spring Hibernate Transaction management Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Spring Hibernate Transaction management

    Hi, I have a question re. Spring and Hibernate in tandem and the transaction management to follow with it. I do not use HibernateTemplate, though I must admit, using it was a breeze, but instead I use the sessionFactory and getCurrentSession() to access the session. Now, when I try and call the DAO method, I get this exception :
    org.hibernate.HibernateException: createQuery is not valid without active transaction
    Shouldn't my AOP configurations take care of beginning a new transaction if there are none? I can do it programmatically, but that doesn't appeal me much! Thanks a lot.


    First, the web-config.xml

    HTML Code:
    	<bean id="hibernateSessionFactory"
    		class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    		<property name="configLocation">
    			<value> WEB-INF/hibernate/hibernate.cfg.xml</value>
    		</property>
    
    		<property name="dataSource" ref="dataSource" />
    
    		<property name="hibernateProperties">
    			<value>
    				hibernate.transaction.factory_class	=org.hibernate.transaction.JDBCTransactionFactory
    			</value>
    		
    		</property>
    
    
    
    	</bean>
    
    
    	<bean id="txManager"
    		class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    		<property name="sessionFactory" ref="hibernateSessionFactory" />
    	</bean>
    
    	<aop:config>
    		<aop:pointcut id="serviceMethods" expression="execution(* com.service.*.*(..))" />
    		<aop:advisor advice-ref="defaultTransactionAdvice"
    			pointcut-ref="serviceMethods" />
    	</aop:config>
    
    
    
    	<tx:advice id="defaultTransactionAdvice" transaction-manager="txManager">
    		<tx:attributes>
    			<tx:method name="*" propagation="REQUIRED" />
    		</tx:attributes>
    	</tx:advice>
    Next, my hibernate.cfg.xml

    HTML Code:
    <hibernate-configuration>
    	<session-factory>
    		<property name="dialect">org.hibernate.dialect.Oracle10gDialect	</property>
    
    		
    		<property name="current_session_context_class">
    			thread
    		</property>
    		
    		
    
    		<!-- this will show us all sql statements -->
    		<property name="hibernate.show_sql"> true	</property>
    		<property name="connection.pool_size">1</property>
    
    
    	</session-factory>
    </hibernate-configuration>
    Finally, my controller snippet:
    Code:
    public class EmployeeController {
    
    @Autowired
    private EmployeeBaseService employeeService;
    @RequestMapping(value = "/employeeHome",method=RequestMethod.GET)
    	public String displayHomePage(@RequestParam("empId") long empId,ModelMap m){
    		System.out.println("employeeHome>> "+empId);
    		//retrieve the employee with this id.
    		
    		Employee employee = null;
    		if(empId ==0){
    			employee = new Employee();
    		}else{
    			employee =employeeService.getEmployeeById(empId);
    		}
    		m.addAttribute("employee",employee);
    		System.out.println(employee);
    		return ProjectConstants.SECURE_FOLDER+"employeeHome";
    	}
    My service class :
    Code:
    package com.service;
    
    public class EmployeeService implements EmployeeBaseService{
    private EmployeeDaoImpl empDaoImpl;
    @Override
    	public List<Employee> getAllLinkedEmployees(long managerId) {
    		return empDaoImpl.getAllLinkedEmployees(managerId);
    	}
    My DAO class
    Code:
    public class EmployeeDaoImpl extends BaseHibernateDaoSupport{
    
    	public List<Employee> getAllLinkedEmployees(long managerId) {
    		// TODO Auto-generated method stub
    		return getSessionFactory().getCurrentSession().createQuery("from Employee").list();
    	}
    }
    
    public abstract class BaseHibernateDaoSupport {
    	private SessionFactory sessionFactory;
    
    	public SessionFactory getSessionFactory() {
    		return sessionFactory;
    	}
    
    	public void setSessionFactory(SessionFactory sessionFactory) {
    		this.sessionFactory = sessionFactory;
    	}
    
    
    
    }

  • #2
    Please use the search as this question has been answered numerous times before.

    In short NEVER NEVER NEVER mess around with the current_session_context_class UNLESS you are using JTA with Spring. Doing this breaks proper tx management.

    On a side note your connection.pool_size property is useless as you are injecting a datasource.

    Comment


    • #3
      Hi Martin, I was hoping that you would reply, as ur replies are extremely precise and I like it.
      However, I did indeed search before, but I couldn't really get a concrete answer. All the bits and pieces which are present in other answers didn't really solve my case. If I don't put the current_session_context_class I get this exception: Whoa!! WTH just happened?

      My code runs fine again. I don't really understand this. Believe me, I did try this, but it was giving me an exception :
      No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here

      I just removed the line: current_session_context_class and it started to work . Incidentally also removed,
      hibernate.transaction.factory_class=org.hibernate. transaction.JDBCTransactionFactory

      Anyways, I am still not sure, why it wasn not working earlier, and why its working now, I dont think my AOP configs. were incorrect as I have not changed them. Anyways, thanks Martin. Now, that the session has been retrieved and I see the 2 statements :open and close session on my logs, so it seems that I dnt have to close any session or do any more session related manipulations, which is great. Just to pick your brain, if you have some more time, do you see any more issues with my configurations? Agreed on the pooling size thing. This is just a POC.

      Just for my reference,
      Code:
      [21/05/12 07:26:05:005 SGT] DEBUG support.HandlerMethodInvoker: Invoking request handler method: public java.lang.String com.spring.controller.EmployeeController.displayHomePage(long,org.springframework.ui.ModelMap)
      [21/05/12 07:26:05:005 SGT] DEBUG hibernate3.HibernateTransactionManager: Creating new transaction with name [com.service.EmployeeService.getEmployeeById]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT[21/05/12 07:26:05:005 SGT] DEBUG impl.SessionImpl: opened session at timestamp: 13375995652
      [21/05/12 07:26:05:005 SGT] DEBUG hibernate3.HibernateTransactionManager: Opened new Session [org.hibernate.impl.SessionImpl@e6529c] for Hibernate transaction[21/05/12 07:26:05:005 SGT] DEBUG hibernate3.HibernateTransactionManager: Preparing JDBC Connection of Hibernate Session [org.hibernate.impl.SessionImpl@e6529c]
      [21/05/12 07:26:05:005 SGT] DEBUG transaction.JDBCTransaction: begin
      [21/05/12 07:26:05:005 SGT] DEBUG jdbc.ConnectionManager: opening JDBC connection
      [21/05/12 07:26:05:005 SGT] DEBUG transaction.JDBCTransaction: current autocommit status: true
      [21/05/12 07:26:05:005 SGT] DEBUG transaction.JDBCTransaction: disabling autocommit
      [21/05/12 07:26:05:005 SGT] DEBUG hibernate3.HibernateTransactionManager: Exposing Hibernate transaction as JDBC transaction [jdbc:oracle:thin:@*, UserName=*, Oracle JDBC driver]
      [21/05/12 07:26:05:005 SGT] DEBUG loader.Loader: loading entity: [com.spring.model.Employee#92179046]
      [21/05/12 07:26:05:005 SGT] DEBUG jdbc.AbstractBatcher: about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
      [21/05/12 07:26:05:005 SGT] DEBUG hibernate.SQL: select employee0_.empId as empId0_0_, employee0_.version as version0_0_, employee0_.firstname as firstname0_0_, employee0_.lastname as lastname0_0_, employee0_.emailid as emailid0_0_, employee0_.filedata as filedata0_0_, employee0_.fileName as fileName0_0_, employee0_.fileContentType as fileCont8_0_0_ from employee employee0_ where employee0_.empId=?
      [21/05/12 07:26:05:005 SGT] DEBUG jdbc.AbstractBatcher: about to open ResultSet (open ResultSets: 0, globally: 0)
      [21/05/12 07:26:05:005 SGT] DEBUG loader.Loader: result row: EntityKey[com.spring.model.Employee#92179046]
      [21/05/12 07:26:05:005 SGT] DEBUG jdbc.AbstractBatcher: about to close ResultSet (open ResultSets: 1, globally: 1)
      [21/05/12 07:26:05:005 SGT] DEBUG jdbc.AbstractBatcher: about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
      [21/05/12 07:26:05:005 SGT] DEBUG engine.TwoPhaseLoad: resolving associations for [com.spring.model.Employee#92179046]
      [21/05/12 07:26:05:005 SGT] DEBUG engine.TwoPhaseLoad: done materializing entity [com.spring.model.Employee#92179046]
      [21/05/12 07:26:05:005 SGT] DEBUG engine.StatefulPersistenceContext: initializing non-lazy collections
      [21/05/12 07:26:05:005 SGT] DEBUG loader.Loader: done entity load
      [21/05/12 07:26:05:005 SGT] DEBUG hibernate3.HibernateTransactionManager: Initiating transaction commit
      [21/05/12 07:26:05:005 SGT] DEBUG hibernate3.HibernateTransactionManager: Committing Hibernate transaction on Session [org.hibernate.impl.SessionImpl@e6529c]
      [21/05/12 07:26:05:005 SGT] DEBUG transaction.JDBCTransaction: commit
      [21/05/12 07:26:05:005 SGT] DEBUG def.AbstractFlushingEventListener: processing flush-time cascades
      [21/05/12 07:26:05:005 SGT] DEBUG def.AbstractFlushingEventListener: dirty checking collections
      [21/05/12 07:26:05:005 SGT] DEBUG def.AbstractFlushingEventListener: Flushed: 0 insertions, 0 updates, 0 deletions to 1 objects
      [21/05/12 07:26:05:005 SGT] DEBUG def.AbstractFlushingEventListener: Flushed: 0 (re)creations, 0 updates, 0 removals to 0 collections
      [21/05/12 07:26:05:005 SGT] DEBUG pretty.Printer: listing entities:
      [21/05/12 07:26:05:005 SGT] DEBUG pretty.Printer: com.spring.model.Employee{fileContentType=application/octet-stream, email=new, fileName=null, empId=92179046, lastname=new, firstname=new, fileDataBytes=null, version=0}
      [21/05/12 07:26:05:005 SGT] DEBUG transaction.JDBCTransaction: re-enabling autocommit
      [21/05/12 07:26:05:005 SGT] DEBUG transaction.JDBCTransaction: committed JDBC Connection[21/05/12 07:26:05:005 SGT] DEBUG jdbc.ConnectionManager: transaction completed on session with on_close connection release mode; be sure to close the session to release JDBC resources!
      [21/05/12 07:26:05:005 SGT] DEBUG hibernate3.HibernateTransactionManager: Closing Hibernate Session [org.hibernate.impl.SessionImpl@e6529c] after transaction
      Last edited by ani_anirban; May 21st, 2012, 06:34 AM.

      Comment


      • #4
        No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
        Which indicates that there was something wrong with your tx setup (ie no transactions applied, could be wrong pointcut etc.).

        Further your config seems fine, although I would remove the hibernate.cfg.xml and simply put those properties in the xml file (saves you another xml file) which also allows for Spring to use property placeholders to replace some values (which can be handy for testing).

        Comment


        • #5
          Originally posted by Marten Deinum View Post
          Which indicates that there was something wrong with your tx setup (ie no transactions applied, could be wrong pointcut etc.).

          Further your config seems fine, although I would remove the hibernate.cfg.xml and simply put those properties in the xml file (saves you another xml file) which also allows for Spring to use property placeholders to replace some values (which can be handy for testing).
          Thanks a lot Marten(Apologies for incorrectly spelling ur name earlier). Yes that wud be my guess, as after I changed the tx:advice, the same exception was thrown. For having a separate hibernate.cfg.xml, my logic is less coupling with Spring, so that I can use it anywhere else.(on a non Spring application) Isn't that the reason why HibernateTemplate was deprecated in the 1st place(for decoupling I mean). Thanks again.

          Comment


          • #6
            Isn't that the reason why HibernateTemplate was deprecated in the 1st place(for decoupling I mean).
            No that isn't the reason. The reason was that as of Hibernate 3.0.1 there is better support for session integration and that all exceptions are now runtime exceptions, before that that wasn't the case and HibernateTemplate was a better solution then plain hibernate. With those flaws fixed HibernateTemplate doesn't have any benefit over a plain SessionFactory/Session approach (exception translation is still done but in a different manner).

            Comment


            • #7
              Originally posted by Marten Deinum View Post
              No that isn't the reason. The reason was that as of Hibernate 3.0.1 there is better support for session integration and that all exceptions are now runtime exceptions, before that that wasn't the case and HibernateTemplate was a better solution then plain hibernate. With those flaws fixed HibernateTemplate doesn't have any benefit over a plain SessionFactory/Session approach (exception translation is still done but in a different manner).
              Okey, thanks Marten.

              Comment

              Working...
              X