Hibernate configuring multiple datasources and multiple session factories
Asked Answered
I

4

19

I am using Spring and Hibernate the spring configuration is as below. How do i configure two data sources, session factories. The transaction is managed using annotations. Please advise

<!-- we can use annotations -->
<context:annotation-config/>

<!-- package to look for annotated classes -->
<context:component-scan base-package="com.XXX.XXX.service.impl"/>

<!-- we will manage transactions with annotations -->
<tx:annotation-driven/>


<bean id="transactionManager"   class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>

<!-- configure hibernate session factory -->

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
    destroy-method="close" p:driverClassName="com.microsoft.sqlserver.jdbc.SQLServerDriver"
    p:url="jdbc:sqlserver://DB_NAME\DB_INSTANCE:DB_PORT;databaseName=DB_NAME;username=DB_USER;password=DB_PASSWORD;" />

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
   <property name="dataSource" ref="dataSource" />
    <property name="configLocation">
            <value>classpath:hibernate.cfg.xml</value>
    </property>
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</prop>
            <prop key="hibernate.current_session_context_class">thread</prop>
            <prop key="show_sql">false</prop>
        </props>
    </property>

</bean>
Incult answered 12/12, 2013 at 11:2 Comment(0)
I
22
<!-- configure hibernate session factory for FirstDB -->

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
    destroy-method="close" p:driverClassName="com.microsoft.sqlserver.jdbc.SQLServerDriver"
    p:url="jdbc:sqlserver://${FirstDB_DB_HosName}\${FirstDB_DB_instanceName}:${FirstDB_DB_PortNumber};databaseName=${FirstDB_DB_DatabaseName};username=${FirstDB_DB_UserName};password=${FirstDB_DB_Password};" />

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
   <property name="dataSource" ref="dataSource" />
    <property name="configLocation">
            <value>classpath:hibernate.cfg.xml</value>
    </property>
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</prop>
            <prop key="hibernate.current_session_context_class">thread</prop>
            <prop key="show_sql">false</prop>
        </props>
    </property>

</bean>


 <!-- configure hibernate session factory for SecondDB database -->

<bean id="SecondDBdataSource" class="org.apache.commons.dbcp.BasicDataSource"
    destroy-method="close" p:driverClassName="com.microsoft.sqlserver.jdbc.SQLServerDriver"
    p:url="jdbc:sqlserver://${SecondDB_DB_HOST}\${SecondDB_DB_INSTANCE}:${SecondDB_DB_PORT};databaseName=${SecondDB_DB_DATABASENAME};username=${SecondDB_DB_USERNAME};password=${SecondDB_DB_PASSWORD};" />


 <bean id="secondDBSessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
   <property name="dataSource" ref="SecondDBdataSource" />
    <property name="configLocation">
            <value>classpath:hibernate-SecondDB.cfg.xml</value>
    </property>
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</prop>
            <prop key="hibernate.current_session_context_class">thread</prop>
            <prop key="show_sql">false</prop>
        </props>
    </property> 

</bean>

In the Hibernate DAO we can use @Qualifier annotation as below to wire the 2 session factories

/**
 * Basic DAO operations dependent with Hibernate's specific classes
 * @see SessionFactory
 */
@Transactional(propagation= Propagation.REQUIRED, readOnly=false)
public class HibernateDao<E, K extends Serializable> implements GenericDao<E, K> {

  @Autowired
  @Qualifier(value="sessionFactory")
  private SessionFactory sessionFactory;

  @Autowired
  @Qualifier(value="secondDBSessionFactory")
  private SessionFactory secondDBSessionFactory;


  protected Class<? extends E> daoType;

  public HibernateDao() {
    daoType = (Class<E>) ((ParameterizedType) getClass().getGenericSuperclass())
                    .getActualTypeArguments()[0];
  }

  //Remaining Code
}
Incult answered 16/1, 2014 at 9:13 Comment(2)
wot about without spring ?Verdellverderer
Note that both SessionFactories/Datasource will share the same transaction manager unless you qualify them as well. Check this linkFavien
M
2

You can show that simple configuration in my project

 <context:component-scan base-package="it.dommy.portmaga" />

<context:property-placeholder location="default.properties" />

<!-- Enable annotation style of managing transactions -->
<tx:annotation-driven />

<context:annotation-config/>


<bean id="dataSource"class="com.mchange.v2.c3p0.ComboPooledDataSource"
      destroy-method="close" >
    <property name="driverClass" value="${db.driverClassName}" />
    <property name="jdbcUrl" value="${db.url}" />
    <property name="user" value="${db.username}" />
    <property name="password" value="${db.password}" />
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">${hibernate.dialect}</prop>
            <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
            <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
            <prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
            <prop key="hibernate.hbm2ddl.auto">create-drop</prop>
            <!--<prop key="hibernate.use_sql_comments">${hibernate.use_sql_comments}</prop>-->
            <!--<prop key="hibernate.validator.apply_to_ddl">${hibernate.validator.apply_to_ddl}</prop>-->
            <!--<prop key="hibernate.max_fetch_depth">${hibernate.max_fetch_depth}</prop>-->
            <!--<prop key="hibernate.default_batch_fetch_size">${hibernate.default_batch_fetch_size}</prop>-->
            <!--<prop key="hibernate.jdbc.batch_size">${hibernate.jdbc.batch_size}</prop>-->
            <!--<prop key="hibernate.validator.autoregister_listeners">true</prop>-->
            <!-- This will drop our existing database and re-create a new one. -->

        </props>
    </property>
    <property name="packagesToScan">
        <list>
            <value>it.dommy.portmaga.model.mysql</value>
        </list>
    </property>
</bean>

<bean id="secondDBdataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
      destroy-method="close">
<property name="driverClass" value="${dba.driverClassName}" />
<property name="jdbcUrl" value="${dba.url}" />
<property name="user" value="${dba.username}" />
<property name="password" value="${dba.password}" />
</bean>

<bean id="secondSessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="secondDBdataSource" />
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">${hibernate.a.dialect}</prop>
            <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
        </props>
    </property>
    <property name="packagesToScan">
        <list>
            <value>it.dommy.portmaga.model.access</value>
        </list>
    </property>
</bean>

<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
    <property name="sessionFactory" ref="secondSessionFactory" />

</bean>

if you wont show all project go here: https://bitbucket.org/dgabriele/portmaga

Manufactory answered 28/8, 2015 at 11:4 Comment(1)
Hello, you have here one transaction manager that is referring one sessions factory. How will the other session factory be picked ?? Dont we need another transaction managerKindle
V
1

dispatcher-servlet.xml

                <bean id="full-license-db-dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
                    <property name="driverClassName" value="${db.driver}" />
                    <property name="url" value="${db.full.url}" />
                    <property name="username" value="${db.full.username}" />
                    <property name="password" value="${db.full.password}" />
                </bean>

                <bean id="sessionFactoryFull"
                      class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
                    <property name="packagesToScan"       value="ci.xyz.license.model.entity.full"/>  
                    <property name="dataSource" ref="full-license-db-dataSource" />
                    <property name="hibernateProperties">
                        <props>
                            <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}    </prop>
                            <prop key="hibernate.dialect">${hibernate.dialect}</prop>
                            <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
                        </props>
                    </property>
                </bean>



                <bean id="trial-license-db-dataSource"
                    class="org.springframework.jdbc.datasource.DriverManagerDataSource">
                    <property name="driverClassName" value="${db.driver}" />
                    <property name="url" value="${db.trial.url}" />
                    <property name="username" value="${db.trial.username}" />
                    <property name="password" value="${db.trial.password}" />
                </bean>

                <bean id="sessionFactoryTrial"
                      class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
                    <property name="dataSource" ref="trial-license-db-dataSource" />
                    <property name="packagesToScan" value="ci.xyz.license.model.entity.trial"/>
                    <property name="hibernateProperties">
                        <props>
                            <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
                            <prop key="hibernate.dialect">${hibernate.dialect}</prop>
                            <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
                        </props>
                    </property>
                </bean>

                <bean id="transactionManagerTrial"
                       class="org.springframework.orm.hibernate4.HibernateTransactionManager">
                    <property name="sessionFactory" ref="sessionFactoryTrial" />
                </bean>
                <bean id="transactionManagerFull"         class="org.springframework.orm.hibernate4.HibernateTransactionManager">
                    <property name="sessionFactory" ref="sessionFactoryFull" />
                </bean>
                <tx:annotation-driven transaction-manager="transactionManagerFull" />
                <tx:annotation-driven transaction-manager="transactionManagerTrial" />

Web.xml

                    <filter>
                        <filter-name>hibernateFilterTrial</filter-name>
                        <filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
                        <init-param>
                            <param-name>sessionFactoryBeanName</param-name>
                            <param-value>sessionFactoryTrial</param-value>
                        </init-param>
                    </filter>
                    <filter-mapping>
                        <filter-name>hibernateFilterTrial</filter-name>
                        <url-pattern>/*</url-pattern>
                        <dispatcher>REQUEST</dispatcher>
                        <dispatcher>FORWARD</dispatcher>
                    </filter-mapping>
                                    <filter>
                        <filter-name>hibernateFilterFull</filter-name>
                        <filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
                        <init-param>
                            <param-name>sessionFactoryBeanName</param-name>
                            <param-value>sessionFactoryFull</param-value>
                        </init-param>
                    </filter>
                    <filter-mapping>
                        <filter-name>hibernateFilterFull</filter-name>
                        <url-pattern>/*</url-pattern>
                        <dispatcher>REQUEST</dispatcher>
                        <dispatcher>FORWARD</dispatcher>
                    </filter-mapping>

Java Code of Dao for quick reference

@Repository @Scope(BeanDefinition.SCOPE_PROTOTYPE) public abstract class AbstractHibernateDao implements IBaseDao { private static final Log logger = LogFactory.getLog(AbstractHibernateDao.class);

      @Autowired
      protected SessionFactory sessionFactoryFull;

      @Autowired
      protected SessionFactory sessionFactoryTrial;



      protected Class<T> persistentClass;

Vo answered 7/9, 2015 at 18:27 Comment(0)
C
0

Updated Answer for new version Hibernate
Since hibernate 5 version, you must define transaction manger for every data source but if you are using general @Transaction annotation in your source code this will make confusion for transaction manager which one to pick, hibernate by default take the first define transaction manager in your xml file and use for all @Transaction annotation on any code. To avoid this problem you need to define transaction manager manually for every @Transaction on you code. Example:

  <!-- Step 1: Define First Database DataSource / connection pool -->
<bean id="myDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
      destroy-method="close">
    <property name="driverClass" value="com.mysql.jdbc.Driver"/>
    <property name="jdbcUrl"
              value="jdbc:mysql://localhost:3306/spring_security_custom_user_demo?allowPublicKeyRetrieval=true&amp;useSSL=false&amp;serverTimezone=UTC"/>
    <property name="user" value="{user}"/>
    <property name="password" value="{password}"/>

    <!-- these are connection pool properties for C3P0 -->
    <property name="minPoolSize" value="4"/>
    <property name="maxPoolSize" value="20"/>
    <property name="maxIdleTime" value="30000"/>
    <property name="initialPoolSize" value="5"/>
</bean>

<!-- Step 2: Setup Hibernate session factory -->
<bean id="sessionFactory"
      class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
    <property name="dataSource" ref="myDataSource"/>
    <property name="packagesToScan" value="com.springdemo.entity"/>
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
            <prop key="hibernate.show_sql">true</prop>
        </props>
    </property>
</bean>

<!-- Step 3: Setup Hibernate transaction manager -->
<bean id="myTransactionManager"
      class="org.springframework.orm.hibernate5.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory"/>
</bean>


<!-- end -->

<!-- Step 1: Define Second Database DataSource / connection pool -->
<bean id="myDataSource2" class="com.mchange.v2.c3p0.ComboPooledDataSource"
      destroy-method="close">
    <property name="driverClass" value="com.mysql.jdbc.Driver"/>
    <property name="jdbcUrl"
              value="jdbc:mysql://localhost:3306/web_customer_tracker?allowPublicKeyRetrieval=true&amp;useSSL=false&amp;serverTimezone=UTC"/>
    <property name="user" value="{user}"/>
    <property name="password" value="{password}"/>

    <!-- these are connection pool properties for C3P0 -->
    <property name="minPoolSize" value="4"/>
    <property name="maxPoolSize" value="20"/>
    <property name="maxIdleTime" value="30000"/>
    <property name="initialPoolSize" value="5"/>
</bean>

<!-- Step 2: Setup Hibernate session factory -->
<bean id="sessionFactory2"
      class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
    <property name="dataSource" ref="myDataSource2"/>
    <property name="packagesToScan" value="com.springdemo.entity"/>
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
            <prop key="hibernate.show_sql">true</prop>
        </props>
    </property>
</bean>

<!-- Step 3: Setup Hibernate transaction manager -->
<bean id="myTransactionManager2"
      class="org.springframework.orm.hibernate5.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory2"/>
</bean>

<!-- Step 4: Enable configuration of transactional behavior based on annotations -->
<tx:annotation-driven transaction-manager="myTransactionManager"/>
<tx:annotation-driven  transaction-manager="myTransactionManager2"/>

Here is @Transaction annotation example.

    @Transactional("myTransactionManager")
    public User findByUsername(String username) {
          return userDao.findByUsername(username);

  }

And if you need to refer to another transaction manager that uses another dataSource.

    @Transactional("myTransactionManager2")
    public User findByUsername(String username) {
          return userDao.findByUsername(username);

  }
Catherinacatherine answered 2/10, 2020 at 1:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.