Hi all,

I am currently working on a webservice that under the hood needs to provide data from/to several unterlying databases.
To achieve that I am using a DAOs with a hibernateTemplate. The all inherit from a base class which looks like this
Code:
public abstract class BaseCrudDao<T extends Serializable> implements BaseDao<T> {

  private static final Logger LOGGER = Logger.getLogger(BaseCrudDao.class);

  protected HibernateTemplate hibernateTemplate;

  protected Class<T> clazz;

  public BaseCrudDao(Class<T> clazz) {
    super();
    this.clazz = clazz;
  }

  /**
   * 
   * @param sessionFactory
   */
  @Autowired
  public void initializeDao(SessionFactory sessionFactory) {
    hibernateTemplate = new HibernateTemplate(sessionFactory);
  }
....
}
Now in order to serve various databases, databse selection based on the incoming request, I was playing around with AbstractRoutingDatasource. MY hibernate configuration to achieve that looks like this.

Code:
<beans>
...
  <bean id="managingDataSource" class="test.DatabaseRoutingDataSource">
    <property name="targetDataSources">
      <map key-type="java.lang.String">
        <entry key="AX1" value-ref="childDataSource"/>
        <entry key="AX2" value-ref="childDataSource2"/>
      </map>
    </property>
    <property name="defaultTargetDataSource" ref="childDataSource" />
  </bean>

  <bean id="parentDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close" abstract="true">
    <property name="driverClass" value="${jdbc.driver.classname}" />
  </bean>
  
  <bean id="childDataSource" parent="parentDataSource"
    destroy-method="close">
    <property name="jdbcUrl" value="${jdbc.ax1.url}" />
    <property name="user" value="${jdbc.ax1.username}" />
    <property name="password" value="${jdbc.ax1.password}" />
  </bean>

  <bean id="childDataSource2" parent="parentDataSource"
    destroy-method="close">
    <property name="jdbcUrl" value="${jdbc.ax2.url}" />
    <property name="user" value="${jdbc.ax2.username}" />
    <property name="password" value="${jdbc.ax2.password}" />
  </bean>
  
  <bean id="sessionFactory" 
    class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
    <property name="dataSource" ref="managingDataSource" />
    <property name="packagesToScan" value="test.ws" />
    <property name="hibernateProperties">
      <props>
        <prop key="hibernate.dialect">${jdbc.hibernate.dialect}</prop>
        <prop key="hibernate.hbm2ddl.auto">${jdbc.hibernate.hbm2ddl.auto}</prop>
        <prop key="hibernate.show_sql">${jdbc.hibernate.showSql}</prop>
      </props>
    </property>
  </bean>
...
</beans>
Now this seems a bit odd to me, first off all only the default datasource is initialized when the session Factory is instantiated. I get the reason why this is happening, still this is a unwanted side-effect.
Secondly it feels a bit off when sessions from different datasources are provided by one SessionFactory, as all the hibernate configuration, intended for a single database instance is applied over all datasources, incl. e.g. the session count etc.
So I wanted to implement a wrapper that implements the SessionFactory interface that more or less provides the AbstractRoutingDataSource functionality and looks as follows:

Code:
public class DatabaseRoutingSessionFactory implements SessionFactory {

  /**
   * 
   */
  private static final long serialVersionUID = 2257846544223138903L;

  private static final ThreadLocal<String> systemNameHolder = new ThreadLocal<String>();

  private Map<String, SessionFactory> sessionFactories;

  /**
   * 
   * @param systemName
   */
  public synchronized static void setSystemName(String systemName) {
    systemNameHolder.set(systemName);
  }

  /**
   * 
   * @return
   */
  public synchronized static String getSystemName() {
    return systemNameHolder.get();
  }

  /**
   * 
   */
  public synchronized static void clearSystemName() {
    systemNameHolder.remove();
  }

  /**
   * @return the sessionFactories
   */
  public synchronized Map<String, SessionFactory> getSessionFactories() {
    return sessionFactories;
  }

  /**
   * @param sessionFactories
   *          the sessionFactories to set
   */
  public synchronized void setSessionFactories(Map<String, SessionFactory> sessionFactories) {
    this.sessionFactories = sessionFactories;
  }

  @Override
  public synchronized Reference getReference() throws NamingException {
    return sessionFactories.get(getSystemName()).getReference();
  }

  @Override
  public synchronized void close() throws HibernateException {
    sessionFactories.get(getSystemName()).close();
  }

//remaining implementation of SessionFactory interface

.... 

}
and changes my hibernate-configuration accordingly:

Code:
<beans>
  ....
  <bean id="managingSessionFactory" class=test.DatabaseRoutingSessionFactory">
    <property name="sessionFactories">
      <map key-type="java.lang.String" value-type="org.hibernate.SessionFactory">
        <entry key="AX1" value-ref="sessionFactory1" />
        <entry key="AX2" value-ref="sessionFactory2" />
      </map>
    </property>
  </bean>

  <bean id="childDataSource1" class="com.mchange.v2.c3p0.ComboPooledDataSource"
    destroy-method="close">
    <property name="driverClass" value="${jdbc.driver.classname}" />
    <property name="jdbcUrl" value="${jdbc.ax1.url}" />
    <property name="user" value="${jdbc.ax1.username}" />
    <property name="password" value="${jdbc.ax1.password}" />
  </bean>
  
  <bean id="childDataSource2" class="com.mchange.v2.c3p0.ComboPooledDataSource"
    destroy-method="close">
    <property name="driverClass" value="${jdbc.driver.classname}" />
    <property name="jdbcUrl" value="${jdbc.ax2.url}" />
    <property name="user" value="${jdbc.ax2.username}" />
    <property name="password" value="${jdbc.ax2.password}" />
  </bean>
  
  <bean id="parentSessionFactory" abstract="true">
    <property name="packagesToScan" value="test" />
    <property name="hibernateProperties">
      <props>
        <prop key="hibernate.dialect">${jdbc.hibernate.dialect}</prop>
        <prop key="hibernate.hbm2ddl.auto">${jdbc.hibernate.hbm2ddl.auto}</prop>
        <prop key="hibernate.show_sql">${jdbc.hibernate.showSql}</prop>
      </props>
    </property>
  </bean>
  
  <bean id="sessionFactory1" 
    class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean" autowire-candidate="false">
    <property name="dataSource" ref="childDataSource1" />
  </bean>
  
  <bean id="sessionFactory2" 
    class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean" autowire-candidate="false">
    <property name="dataSource" ref="childDataSource2" />
  </bean>
  ...
</beans>
Do you have any ideas or negative implications I am missing out on?? Maybe even a Standard Spring solution exists for this problem?? Any input and help is more than appreciated!

Thanks in advance!

Iulius