spring+hibernate配置多数据源

spring+hibernate配置多数据源及多个事务过程

  • 在datasource.properties文件中增加数据库配置
sqlServer.jdbc.url=jdbc:sqlserver://127.0.0.1:1433;databaseName=db_ceshi1
sqlServer.jdbc.user=sa
sqlServer.jdbc.password=sa
sqlServer.jdbc.initialPoolSize=5
sqlServer.jdbc.minPoolSize=5
sqlServer.jdbc.maxPoolSize=80
sqlServer.jdbc.checkoutTimeout=20000
sqlServer.jdbc.idleConnectionTestPeriod=120
sqlServer.jdbc.maxIdleTime=60
sqlServer.jdbc.maxStatements=6000
sqlServer.jdbc.testConnectionOnCheckout=false

sqlServer.jdbc.erms.driverClass=com.microsoft.sqlserver.jdbc.SQLServerDriver
sqlServer.jdbc.erms.url=jdbc:sqlserver://127.0.0.1:1433;databaseName=db_ceshi2
sqlServer.jdbc.erms.user=sa
sqlServer.jdbc.erms.password=sa
sqlServer.jdbc.erms.initialPoolSize=5
sqlServer.jdbc.erms.minPoolSize=5
sqlServer.jdbc.erms.maxPoolSize=80
sqlServer.jdbc.erms.checkoutTimeout=20000
sqlServer.jdbc.erms.idleConnectionTestPeriod=120
sqlServer.jdbc.erms.maxIdleTime=60
sqlServer.jdbc.erms.maxStatements=6000
sqlServer.jdbc.erms.testConnectionOnCheckout=false
  • 在spring.xml文件中配置数据源级事务
    <bean id="dataSourceSqlServer" class="com.mchange.v2.c3p0.ComboPooledDataSource"
        destroy-method="close">
        <property name="driverClass" value="${sqlServer.jdbc.driverClass}" />
        <property name="jdbcUrl" value="${sqlServer.jdbc.url}" />
        <property name="user" value="${sqlServer.jdbc.user}" />
        <property name="password" value="${sqlServer.jdbc.password}" />
        <property name="initialPoolSize" value="${sqlServer.jdbc.initialPoolSize}" />
        <property name="minPoolSize" value="${sqlServer.jdbc.minPoolSize}" />
        <property name="maxPoolSize" value="${sqlServer.jdbc.maxPoolSize}" />
        <property name="checkoutTimeout" value="${sqlServer.jdbc.checkoutTimeout}" />
        <property name="idleConnectionTestPeriod" value="${sqlServer.jdbc.idleConnectionTestPeriod}" />
        <property name="maxIdleTime" value="${sqlServer.jdbc.maxIdleTime}" />
        <property name="maxStatements" value="${sqlServer.jdbc.maxStatements}" />
        <property name="testConnectionOnCheckout" value="${sqlServer.jdbc.testConnectionOnCheckout}" />
    </bean>

    <bean id="dataSource" class="com.hebky.erms.util.core.DynamicDataSource">
        <property name="targetDataSources">
            <map key-type="java.lang.String">
                <entry key="dataSourceMySql" value-ref="dataSourceMySql" />
                <entry key="dataSourceSqlServer" value-ref="dataSourceSqlServer" />
            </map>
        </property>
        <property name="defaultTargetDataSource" ref="dataSourceSqlServer" />
    </bean>

    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="configLocation" value="classpath:hibernate.cfg.xml" />
        <!-- 通过扫描包的方式扫描所有实体类 -->
        <property name="packagesToScan">
            <list>
                <value>com.ceshi.*</value>
            </list>
        </property>
    </bean>

    <!-- 配置事务管理器 -->
    <bean id="transactionManager"
        class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory"></property>
        <property name="nestedTransactionAllowed" value="true"></property>
    </bean>

    <!-- 拦截器方式配配置事务 -->
    <tx:advice id="txadvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="add*" propagation="REQUIRED" />
            <tx:method name="save*" propagation="REQUIRED" />
            <tx:method name="saveRN*" propagation="REQUIRES_NEW" />
            <tx:method name="import*" propagation="REQUIRED" />
            <tx:method name="update*" propagation="REQUIRED" />
            <tx:method name="saveNS*" propagation="NOT_SUPPORTED" />
            <tx:method name="updateNS*" propagation="NOT_SUPPORTED" />
            <tx:method name="executeNS*" propagation="REQUIRED" />
            <tx:method name="updateRN*" propagation="REQUIRES_NEW" />
            <tx:method name="delete*" propagation="REQUIRED" no-rollback-for="NotImplementedException"/>
            <tx:method name="get*" read-only="true" propagation="REQUIRED" />
            <tx:method name="find*" read-only="true" propagation="REQUIRED" />
            <tx:method name="query*" read-only="true" propagation="REQUIRED" />
            <tx:method name="count*" read-only="true" propagation="REQUIRED" />
            <tx:method name="isNS*" read-only="true" propagation="NOT_SUPPORTED" />
            <tx:method name="*" read-only="true" />
        </tx:attributes>
    </tx:advice>
    <aop:config>
        <aop:pointcut id="serviceMethods"
            expression="execution(* com.ceshi..service..*.*(..))" />
        <aop:advisor advice-ref="txadvice" pointcut-ref="serviceMethods" />
    </aop:config>

    <!--从数据库配置-->
    <bean id="dataSourcecm" class="com.mchange.v2.c3p0.ComboPooledDataSource" >
        <property name="driverClass" value="${sqlServer.jdbc.erms.driverClass}" />
        <property name="jdbcUrl" value="${sqlServer.jdbc.erms.url}" />
        <property name="user" value="${sqlServer.jdbc.erms.user}" />
        <property name="password" value="${sqlServer.jdbc.erms.password}" />
        <property name="initialPoolSize" value="${sqlServer.jdbc.erms.initialPoolSize}" />
        <property name="minPoolSize" value="${sqlServer.jdbc.erms.minPoolSize}" />
        <property name="maxPoolSize" value="${sqlServer.jdbc.erms.maxPoolSize}" />
        <property name="checkoutTimeout" value="${sqlServer.jdbc.erms.checkoutTimeout}" />
        <property name="idleConnectionTestPeriod" value="${sqlServer.jdbc.erms.idleConnectionTestPeriod}" />
        <property name="maxIdleTime" value="${sqlServer.jdbc.erms.maxIdleTime}" />
        <property name="maxStatements" value="${sqlServer.jdbc.erms.maxStatements}" />
        <property name="testConnectionOnCheckout" value="${sqlServer.jdbc.erms.testConnectionOnCheckout}" />
    </bean>

    <!--session工厂-->
    <bean id="sessionFactorycm" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" >
        <property name="dataSource" ref="dataSourcecm" />
        <!--包扫描,数据库对应的实体类所在的包-->
        <!-- 通过扫描包的方式扫描所有实体类 -->
        <property name="packagesToScan">
            <list>
                <value>com.ceshi.*</value>
            </list>
        </property>
        <property name="hibernateProperties">
            <value>
                <!-- hibernate使用的数据库方言(即连接哪种数据库) -->
                hibernate.dialect = org.hibernate.dialect.SQLServerDialect
                <!-- 自动更新数据库表结构 -->
                hibernate.hbm2ddl.auto = update
                <!-- 后台显示sql语句,开发时使用-->
                hibernate.show_sql = true
                <!-- 是否格式化SQL -->
                hibernate.format_sql = true
            </value>
        </property>
    </bean>

    <!--事务管理器-->
    <bean id="transactionManagercm" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactorycm"/>
    </bean>

    <!-- 配置事务通知属性 -->
    <tx:advice id="transactionAdvicecm" transaction-manager="transactionManagercm">
        <!-- 定义事务传播属性 -->
        <tx:attributes>
            <tx:method name="add*" propagation="REQUIRED" />
            <tx:method name="save*" propagation="REQUIRED" />
            <tx:method name="saveRN*" propagation="REQUIRES_NEW" />
            <tx:method name="import*" propagation="REQUIRED" />
            <tx:method name="update*" propagation="REQUIRED" />
            <tx:method name="saveNS*" propagation="NOT_SUPPORTED" />
            <tx:method name="updateNS*" propagation="NOT_SUPPORTED" />
            <tx:method name="executeNS*" propagation="REQUIRED" />
            <tx:method name="updateRN*" propagation="REQUIRES_NEW" />
            <tx:method name="delete*" propagation="REQUIRED" no-rollback-for="NotImplementedException"/>
            <tx:method name="get*" read-only="true" propagation="REQUIRED" />
            <tx:method name="find*" read-only="true" propagation="REQUIRED" />
            <tx:method name="query*" read-only="true" propagation="REQUIRED" />
            <tx:method name="count*" read-only="true" propagation="REQUIRED" />
            <tx:method name="isNS*" read-only="true" propagation="NOT_SUPPORTED" />
            <tx:method name="*" read-only="true" />
        </tx:attributes>
    </tx:advice>

    <!-- 配置事务切面 -->
    <aop:config>
        <aop:advisor pointcut="execution(* com.ceshi..service..*.*(..))" advice-ref="transactionAdvicecm"/>
    </aop:config>
  • 创建DatabaseContextHolder类
class DatabaseContextHolder {
    public static final String DATA_SOURCE_SQLSERVER = "dataSourceSqlServer";
    public static final String DATA_SOURCE_ERMS = "dataSourcecm";


    private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>(); // 线程本地环境

    /**
     * 设置数据源类型
     *
     * @param customerType 数据源类型
     */
    public static void setCustomerType(String customerType) {
        contextHolder.set(customerType);
    }

    /**
     * 获取数据源类型
     *
     * @return
     */
    static String getCustomerType() {
        return contextHolder.get();
    }

    /**
     * 清除数据源类型
     */
    public static void clearCustomerType() {
        contextHolder.remove();
    }
}
  • 创建DynamicDataSource继承AbstractRoutingDataSource获取动态数据源
public class DynamicDataSource extends AbstractRoutingDataSource {

    /**
     * 在进行DAO操作前,通过上下文环境变量,获得数据源的类型
     */
    @Override
    protected Object determineCurrentLookupKey() {
        return DatabaseContextHolder.getCustomerType();
    }

}
  • 在BaseDao中注入session即可
public abstract class BaseDao implements IBaseDao {

    @Resource
    private SessionFactory sessionFactory;// 从容器中注入session工厂【无需get,set方法】

    @Resource
    private SessionFactory sessionFactorycm;

    /**
     * 向子类暴露的接口获用来获取session
     *
     * @return session
     */
    protected Session getSession() {
        // 事务必须是开启的(Required),否则获取不到
            return sessionFactory.getCurrentSession();
    }

    //注入第二个session
     protected Session getSessionFactorycm(){
            return sessionFactorycm.getCurrentSession();
        }


    /**
     * 保存实体
     *
     * @param t 实体参数
     */
    public <T> void save(T t) {
        getSession().save(t);
    }
    
    public <T> void saveTwo(T t){
        getSessionFactorycm().save(T);
    }
}

配置多数据源完成

 

posted @ 2019-11-12 17:42  随遇而安~~~  阅读(...)  评论(...编辑  收藏