SSH framework series: Spring configures multiple data sources

The original text comes from: http://www.sjsjw.com/kf_web/article/13_31666_9704.asp

 

1. Introduction of the problem 

         For ordinary SSH frameworks, generally configure a data source, a SessionFactory, a transaction management and the corresponding ProxyCreate. So when the project needs to operate multiple databases, how to configure it? 

plan 1 

Configure 2 data sources, 2 corresponding SessionFactory, 2 transactions, etc. The configuration of Spring is as follows: 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- Introduce datasource configuration file-->
<context:property-placeholder location="classpath:datasource.properties" />
<!--Create mysql jdbc data source-->
<bean id="mysqlDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass" value="${jdbc.mysql.driver}" />
<property name="jdbcUrl" value="${jdbc.mysql.url}" />
<property name="user" value="${jdbc.mysql.username}" />
<property name="password" value="${jdbc.mysql.password}" />
<!-- Specify the minimum number of connections to connect to the database connection pool-->
        <property name="minPoolSize" value="10" />
        <!-- Specify the maximum number of connections to connect to the database connection pool-->
        <property name="maxPoolSize" value="30" />
        <!-- Specify the maximum idle time for connections to the database connection pool -->
        <property name="maxIdleTime" value="1800" />
        <property name="acquireIncrement" value="2" />
        <property name="maxStatements" value="0" />
        <!-- Specify the number of initial connections to connect to the database connection pool-->
        <property name="initialPoolSize" value="2" />
        <property name="idleConnectionTestPeriod" value="1800" />
        <!-- When the connection fails, the number of attempts to reconnect -->
        <property name="acquireRetryAttempts" value="30" />
        <property name="breakAfterAcquireFailure" value="true" />
        <property name="testConnectionOnCheckout" value="false" />
</bean>
<!--Create oracle jdbc data source-->
<bean id="oracleDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass" value="${jdbc.oracle.driver}" />
<property name="jdbcUrl" value="${jdbc.oracle.url}" />
<property name="user" value="${jdbc.oracle.username}" />
<property name="password" value="${jdbc.oracle.password}" />
<!-- Specify the minimum number of connections to connect to the database connection pool-->
        <property name="minPoolSize" value="10" />
        <!-- Specify the maximum number of connections to connect to the database connection pool-->
        <property name="maxPoolSize" value="30" />
        <!-- Specify the maximum idle time for connections to the database connection pool -->
        <property name="maxIdleTime" value="1800" />
        <property name="acquireIncrement" value="2" />
        <property name="maxStatements" value="0" />
        <!-- Specify the number of initial connections to connect to the database connection pool-->
        <property name="initialPoolSize" value="2" />
        <property name="idleConnectionTestPeriod" value="1800" />
        <!-- When the connection fails, the number of attempts to reconnect -->
        <property name="acquireRetryAttempts" value="1" />
        <property name="breakAfterAcquireFailure" value="true" />
        <property name="testConnectionOnCheckout" value="false" />
</bean>
<!-- Create MysqlSessionFactory-->
<bean id="mysqlSessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="mysqlDataSource" />
<property name="hibernateProperties">
<props>
   <prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="current_session_context_class">thread</prop>
</props>
</property>
<property name="mappingResources">
<list>
<value>edu/njupt/zhb/model/mysql/Student.hbm.xml</value>
</list>
</property>
</bean>
 
   <!-- Create OracleSessionFactory-->
<bean id="oracleSessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="oracleDataSource" />
<property name="hibernateProperties">
<props>
   <prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.OracleDialect</prop>
<prop key="current_session_context_class">thread</prop>
</props>
</property>
<property name="mappingResources">
<list>
<value>edu/njupt/zhb/model/oracle/Student.hbm.xml</value>
</list>
</property>
</bean>
 
<!-- Configure Mysql transaction-->
<bean id="mysqlTransactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory">
<ref local="mysqlSessionFactory" />
</property>
</bean>
     <!--Mysql hibernate4 must be configured to enable transactions or getCurrentSession() cannot be obtained -->
<bean id="mysqlTransactionInterceptor"
class="org.springframework.transaction.interceptor.TransactionInterceptor">
<property name="transactionManager">
<ref local="mysqlTransactionManager" />
</property>
<property name="transactionAttributes">
<props>
<prop key="register">PROPAGATION_REQUIRED</prop>
<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="select*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="query*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="sync*">PROPAGATION_REQUIRED</prop>
<prop key="finish*">PROPAGATION_REQUIRED</prop>
<prop key="add*">PROPAGATION_REQUIRED</prop>
<prop key="insert*">PROPAGATION_REQUIRED</prop>
<prop key="edit*">PROPAGATION_REQUIRED</prop>
<prop key="update*">PROPAGATION_REQUIRED</prop>
<prop key="save*">PROPAGATION_REQUIRED</prop>
<prop key="remove*">PROPAGATION_REQUIRED</prop>
<prop key="delete*">PROPAGATION_REQUIRED</prop>
<prop key="modify*">PROPAGATION_REQUIRED</prop>
<prop key="*">PROPAGATION_REQUIRED,-java.lang.Exception</prop>
</props>
</property>
</bean>
 
<!-- Configure oracle transactions-->
<bean id="oracleTransactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory">
<ref local="oracleSessionFactory" />
</property>
</bean>
     <!--Mysql hibernate4 must be configured to enable transactions or getCurrentSession() cannot be obtained -->
<bean id="oracleTransactionInterceptor"
class="org.springframework.transaction.interceptor.TransactionInterceptor">
<property name="transactionManager">
<ref local="oracleTransactionManager" />
</property>
<property name="transactionAttributes">
<props>
<prop key="register">PROPAGATION_REQUIRED</prop>
<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="select*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="query*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="sync*">PROPAGATION_REQUIRED</prop>
<prop key="finish*">PROPAGATION_REQUIRED</prop>
<prop key="add*">PROPAGATION_REQUIRED</prop>
<prop key="insert*">PROPAGATION_REQUIRED</prop>
<prop key="edit*">PROPAGATION_REQUIRED</prop>
<prop key="update*">PROPAGATION_REQUIRED</prop>
<prop key="save*">PROPAGATION_REQUIRED</prop>
<prop key="remove*">PROPAGATION_REQUIRED</prop>
<prop key="delete*">PROPAGATION_REQUIRED</prop>
<prop key="modify*">PROPAGATION_REQUIRED</prop>
<prop key="*">PROPAGATION_REQUIRED,-java.lang.Exception</prop>
</props>
</property>
</bean>
 
<!-- autoproxy automatically creates a proxy -->
      <bean id="ProxyCreator" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
         <property name="beanNames">
             <list>
                <value>*ServiceImpl</value>
             </list>
         </property>
         <property name="interceptorNames">
             <list>
                <value>mysqlTransactionInterceptor</value>
                <value>oracleTransactionInterceptor</value>
             </list>
         </property>
      </bean>
<!--********************************Inject Mysql Dao*********** ************************************-->
<bean id="mysqlBaseDao" class="edu.njupt.zhb.dao.MysqlBaseDao">
    <property name="sessionFactory" ref="mysqlSessionFactory"></property>
    </bean>
    <!--********************************Injecting Oracle Dao*********** ************************************-->
    <bean id="oracleBaseDao" class="edu.njupt.zhb.dao.OracleBaseDao">
    <property name="sessionFactory" ref="oracleSessionFactory"></property>
    </bean>
    <!--********************************Inject Services************ ********************-->
<!--********************************Inject Action************ ********************-->
</beans>

 

 

Analysis of advantages and disadvantages: 

Advantages: We can normally use 2 different Dao in the program, and we can call dao's getSessionFactory().getCurrentSession(), which is very convenient to use. Each Dao has its own transaction management, and the security aspects are the same as a database. 

Disadvantages: Due to the configuration of the transaction and the configuration of the automatic proxy creation, as long as one database cannot be connected, even if the other database can be connected, the entire project still cannot be started normally. For some special application scenarios, this scheme has great defects. 

For example, the requirements of a project are: a project needs to operate two databases at the same time, if one database cannot be connected, then the project operates another database, and at the same time, the operation actions are recorded, and when the other database can be connected, then Previous operations are synchronized to this database. And it is required that when the project starts, even if only one database can be connected, the project still runs normally. 

 

Scenario 2 

In order to solve the above requirements, we use one of the databases as the local database and the other as the remote database. When the remote database cannot be connected, we skip. The entire project can use the local database, and at the same time save the data that needs to be synchronized, and then synchronize when it can be connected. 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- Introduce datasource configuration file-->
<context:property-placeholder location="classpath:datasource.properties" />
<!--Create mysql jdbc data source-->
<bean id="mysqlDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass" value="${jdbc.mysql.driver}" />
<property name="jdbcUrl" value="${jdbc.mysql.url}" />
<property name="user" value="${jdbc.mysql.username}" />
<property name="password" value="${jdbc.mysql.password}" />
<!-- Specify the minimum number of connections to connect to the database connection pool-->
        <property name="minPoolSize" value="10" />
        <!-- Specify the maximum number of connections to connect to the database connection pool-->
        <property name="maxPoolSize" value="30" />
        <!-- Specify the maximum idle time for connections to the database connection pool -->
        <property name="maxIdleTime" value="1800" />
        <property name="acquireIncrement" value="2" />
        <property name="maxStatements" value="0" />
        <!-- Specify the number of initial connections to connect to the database connection pool-->
        <property name="initialPoolSize" value="2" />
        <property name="idleConnectionTestPeriod" value="1800" />
        <!-- When the connection fails, the number of attempts to reconnect -->
        <property name="acquireRetryAttempts" value="30" />
        <property name="breakAfterAcquireFailure" value="true" />
        <property name="testConnectionOnCheckout" value="false" />
</bean>
<!--Create oracle jdbc data source-->
<bean id="oracleDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass" value="${jdbc.oracle.driver}" />
<property name="jdbcUrl" value="${jdbc.oracle.url}" />
<property name="user" value="${jdbc.oracle.username}" />
<property name="password" value="${jdbc.oracle.password}" />
<!-- Specify the minimum number of connections to connect to the database connection pool-->
        <property name="minPoolSize" value="10" />
        <!-- Specify the maximum number of connections to connect to the database connection pool-->
        <property name="maxPoolSize" value="30" />
        <!-- Specify the maximum idle time for connections to the database connection pool -->
        <property name="maxIdleTime" value="1800" />
        <property name="acquireIncrement" value="2" />
        <property name="maxStatements" value="0" />
        <!-- Specify the number of initial connections to connect to the database connection pool-->
        <property name="initialPoolSize" value="2" />
        <property name="idleConnectionTestPeriod" value="1800" />
        <!-- When the connection fails, the number of attempts to reconnect -->
        <property name="acquireRetryAttempts" value="1" />
        <property name="breakAfterAcquireFailure" value="true" />
        <property name="testConnectionOnCheckout" value="false" />
</bean>
<!-- Create MysqlSessionFactory-->
<bean id="mysqlSessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="mysqlDataSource" />
<property name="hibernateProperties">
<props>
   <prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="current_session_context_class">thread</prop>
</props>
</property>
<property name="mappingResources">
<list>
<value>edu/njupt/zhb/model/mysql/Student.hbm.xml</value>
</list>
</property>
</bean>
 
   <!-- Create OracleSessionFactory-->
<bean id="oracleSessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="oracleDataSource" />
<property name="hibernateProperties">
<props>
   <prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.OracleDialect</prop>
<prop key="current_session_context_class">thread</prop>
</props>
</property>
<property name="mappingResources">
<list>
<value>edu/njupt/zhb/model/oracle/Student.hbm.xml</value>
</list>
</property>
</bean>
 
<!-- Configure Mysql transaction-->
<bean id="mysqlTransactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory">
<ref local="mysqlSessionFactory" />
</property>
</bean>
     <!--Mysql hibernate4 must be configured to enable transactions or getCurrentSession() cannot be obtained -->
<bean id="mysqlTransactionInterceptor"
class="org.springframework.transaction.interceptor.TransactionInterceptor">
<property name="transactionManager">
<ref local="mysqlTransactionManager" />
</property>
<property name="transactionAttributes">
<props>
<prop key="register">PROPAGATION_REQUIRED</prop>
<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="select*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="query*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="sync*">PROPAGATION_REQUIRED</prop>
<prop key="finish*">PROPAGATION_REQUIRED</prop>
<prop key="add*">PROPAGATION_REQUIRED</prop>
<prop key="insert*">PROPAGATION_REQUIRED</prop>
<prop key="edit*">PROPAGATION_REQUIRED</prop>
<prop key="update*">PROPAGATION_REQUIRED</prop>
<prop key="save*">PROPAGATION_REQUIRED</prop>
<prop key="remove*">PROPAGATION_REQUIRED</prop>
<prop key="delete*">PROPAGATION_REQUIRED</prop>
<prop key="modify*">PROPAGATION_REQUIRED</prop>
<prop key="*">PROPAGATION_REQUIRED,-java.lang.Exception</prop>
</props>
</property>
</bean>
<!-- autoproxy automatically creates a proxy -->
      <bean id="ProxyCreator" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
         <property name="beanNames">
             <list>
                <value>*ServiceImpl</value>
             </list>
         </property>
         <property name="interceptorNames">
             <list>
                <value>mysqlTransactionInterceptor</value>
             </list>
         </property>
      </bean>
<!--********************************Inject Mysql Dao*********** ************************************-->
<bean id="mysqlBaseDao" class="edu.njupt.zhb.dao.MysqlBaseDao">
    <property name="sessionFactory" ref="mysqlSessionFactory"></property>
    </bean>
    <!--********************************Injecting Oracle Dao*********** ************************************-->
    <bean id="oracleBaseDao" class="edu.njupt.zhb.dao.OracleBaseDao">
    <property name="sessionFactory" ref="oracleSessionFactory"></property>
    </bean>
    <!--********************************Inject Services************ ********************-->
<!--********************************Inject Action************ ********************-->
</beans>

 

 

Under this configuration, the attribute of the data source of oracleBaseDao: the value of acquireRetryAttempts is configured as 1. Even if we cannot connect, we only need to connect once, and there will be no "stuck" situation. Moreover, since we do not configure transactions in oracleBaseDao, dao cannot obtain getCurrentSession, and can only use Hibernate through sessionFactory().openSession(). At the same time, in order to catch exceptions, we set the session to be submitted manually. 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326467146&siteId=291194637