Announcement Announcement Module
Collapse
No announcement yet.
HibernateDaoSupport - Multiple hibernate sessions in a single transaction Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • HibernateDaoSupport - Multiple hibernate sessions in a single transaction

    I have spent more than 18 hours so far trying to figure out what is wrong with the following :

    - I have a set of DAOs extending HibernateDaoSupport
    - I have configured Spring @Transactional annotation support.
    - I have configured HibernateTransactionManager
    - In one of my services I have a transaction which calls different DAOs in a transaction.

    The behavior I am seeing is that the code is executed in a single Transaction however multiple hibernate sessions are being created and closed.

    My understanding is that with the configuration below there is supposed to be a single hibernate session per transaction and this is the configuration i would like to get to.


    The configuration is as follows :


    Code:
    <!-- Normal mysql data source , autoCommit is turned off -->
    <bean id="datasource" class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    <property name="url" value="jdbc:mysql://${mysql.db.host}:${mysql.db.port}/${mysql.db.dbname}" />
    <property name="username" value="${mysql.db.username}" />
    <property name="password" value="${mysql.db.password}" />
    <property name="initialSize" value="${mysql.connection.pool.initialSize}" />
    <property name="maxActive" value="${mysql.connection.pool.maxActive}" />
    <property name="minIdle" value="${mysql.connection.pool.minIdle}" />
    <property name="testWhileIdle" value="true" />
    <property name="validationQuery" value="SELECT 1" />
    <property name="defaultAutoCommit" value="false"></property>
    </bean>
    
    
    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
    
    <property name="exposeTransactionAwareSessionFactory" value="true"></property>
    
    <property name="dataSource" ref="datasource" />
    
    <property name="hibernateProperties">
    <props>
    <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
    <prop key="hibernate.cache.provider_class">org.hibernate.cache.NoCacheProvider</prop>
    <prop key="hibernate.show_sql">true</prop>
    <prop key="hibernate.hbm2ddl.auo">update</prop>
    				<!--<prop key="hibernate.current_session_context_class">org.springframework.orm.hibernate3.SpringSessionContext</prop>  // removed this should be enabled by default-->
    </props>
    </property>
    <property name="packagesToScan">
    <list>
    <value>com.telcocell.snapp.entities.persistable</value>
    </list>
    </property>
    </bean>
    
    	<tx:annotation-driven transaction-manager="transactionManager" />
    
    	<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    		<property name="sessionFactory" ref="sessionFactory"></property>
    	</bean>
    
    <!-- The DAOs -->
    
    	<bean id="userDAO" class="com.telcocell.snapp.dao.UserDAO">
    		 <property name="sessionFactory" ref="sessionFactory"></property> 
    
    
    	</bean>
    
    	<bean id="groupsDao" class="com.telcocell.snapp.dao.GroupsDao">
    		 <property name="sessionFactory" ref="sessionFactory"></property> 
    
    		
    	</bean>




    The code :


    Code:
    @Transactional
    public class SnappStartupService {
    
    
    	private UserDAO userDao;
    
    	private GroupsDao groupDao;
    
    	private PluginsDao pluginsDao;
    
    
    	@Transactional(propagation=Propagation.REQUIRED)
    	public void startSnapp() {
    		if (logger.isInfoEnabled())
    			logger.info("Starting Snapp application ...");
    
    			// save system user
    			userDao.save(systemUser);
    
    			// save admin user
    			userDao.save(adminUser);
    
    			Group usersGroup = new Group();
    			usersGroup.setName(usersGroupName);
    
    			groupDao.save(usersGroup);
    
    			// now add users to groups :
    
    			// System user belongs to all groups :
    
    			List<Group> allGroups = new ArrayList<Group>();
    			allGroups.add(systemGroup);
    			allGroups.add(adminGroup);
    			allGroups.add(usersGroup);
    
    			systemUser.setGroups(allGroups);
    
    			// try something here :
    
    			User someUser = userDao.findByName(systemUser.getUsername());
    
    // this returns null as the transaction did not commit yet
    
    
    
    	}
    
    }

    Can anyone tell me what is it that I am doing wrong? or is there something I am not getting in the session / transaction concept?


    Thanks in advance

  • #2
    You left out the interesting stuff, your dao's... Apart from that don't use HibernateDaoSupport/HibernateTemplate as that isn't recommended anymore.

    Next to that it would be interesting to see how are you testing this.

    Comment


    • #3
      My Daos are nothing fancy. It has save which delegates to hibernateTemplate.save() , load, update,etc..

      Anyways after spending 3 more hours yesterday i figured out the problem

      The transactional method was called as part of the bean creation procedure

      that is (configured to be run by spring as an init-method)

      Code:
      <bean id="snappStartupService" class="com.telcocell.snapp.service.SnappStartupService" init-method="startSnapp">
      
      		<property name="userDao" ref="userDAO"></property>
      		<property name="groupDao" ref="groupsDao"></property>
      		<property name="pluginsDao" ref="pluginsDao"></property>
      >
      So i think that code was not really run in a transaction when it executed because Spring was not creating the proxy yet.

      I introduced an indirection which solved the problem.
      the snapp startup service does not call the startSnapp as an init method, instead another object from another class gets created, the init method for that class calls the startSnapp method on the snappStartupService reference. Now everything works as expected.

      Thanks for your help Marten

      Comment

      Working...
      X