Results 1 to 3 of 3

Thread: HibernateDaoSupport - Multiple hibernate sessions in a single transaction

  1. #1
    Join Date
    Dec 2010
    Posts
    2

    Default 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. #2
    Join Date
    Jun 2006
    Location
    The Netherlands
    Posts
    13,632

    Default

    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.
    Marten Deinum
    Java Consultant / Pragmatist / Open Source Enthousiast / Author


    Pro Spring MVC: With Web Flow
    Conspect

    Have you read the reference guide.
    Use the [ code ] tags, young padawan

  3. #3
    Join Date
    Dec 2010
    Posts
    2

    Default

    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

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •