1

我有 2 个客户端使用部署在 tomcat 中的相同基于 Spring 的 REST 应用程序。根据客户,我需要在数据源和事务管理器之间进行选择。如何在运行时选择使用哪个事务管理器?

    <bean id="First_dataSource" class="org.apache.commons.dbcp.BasicDataSource"
            destroy-method="close">
            <property name="url" value="${First_jdbc.url}" />
            <property name="driverClassName" value="${First_jdbc.driverClassName}" />
            <property name="username" value="${First_jdbc.username}" />
            <property name="password" value="${First_jdbc.password}" />
            <property name="removeAbandoned" value="true" />
            <property name="initialSize" value="20" />
            <property name="maxActive" value="30" />
            <!-- <property name="defaultAutoCommit" value="false" /> -->
   </bean>

    <bean id="Second_dataSource" class="org.apache.commons.dbcp.BasicDataSource"
            destroy-method="close">
            <property name="url" value="${Second_jdbc.url}" />
            <property name="driverClassName" value="${Second_jdbc.driverClassName}" />
            <property name="username" value="${Second_jdbc.username}" />
            <property name="password" value="${Second_jdbc.password}" />
            <property name="removeAbandoned" value="true" />
            <property name="initialSize" value="20" />
            <property name="maxActive" value="30" />
            <!-- <property name="defaultAutoCommit" value="false" /> -->
   </bean>

<bean id="First_TransactionManager"
    class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
        scope="singleton">
        <property name="dataSource" ref="First_dataSource" />
        <qualifier value="SC_TM"></qualifier>
</bean>

<bean id="Second_TransactionManager"
          class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
          scope="singleton">
          <property name="dataSource" ref="Second_dataSource" />
          <qualifier value="Second_TM"></qualifier>
</bean>   

在代码中如何在运行时选择 @Transactional("????") 。如果 org.springframework.jdbc.datasource.DataSourceTransactionManager 不可能,还有其他方法吗?

4

5 回答 5

0

我不知道您为什么要在 2 个事务管理器之间进行更改可能是您需要检查事务管理器链解决方案,但如果您需要这个,您可以在 Repo 方法上添加您的 @transactional 并执行 2 个 Repos 并从服务中管理它层作为开关,否则我相信可以使用 AOP 完成解决方案,但需要更多时间来考虑它。

于 2014-04-06T16:12:51.043 回答
0

使用@Transactional,您可以像这样指定事务管理器:

@Transactional("First_TransactionManager")

或者

@Transactional("Second_TransactionManager")

取决于您要使用哪一个。确保在事务方法中使用正确的实体管理器/会话工厂。那些你还必须指定你想用哪个注入@PersistenceContext("nameOfPersistenceUnit")

于 2014-04-06T11:46:10.980 回答
0
<tx:advice id="First_txAdvice" transaction-manager="First_TransactionManager">
    <tx:attributes>
        <tx:method name="*" propagation="REQUIRED" rollback-for="Exception" />
    </tx:attributes>
</tx:advice>

<aop:config>
    <aop:pointcut id="First_daoimplOperation"
        expression="execution(* in.company.common.service.CommonServiceImpl.*(..))" />

    <aop:advisor advice-ref="First_txAdvice" pointcut-ref="First_daoimplOperation" />
</aop:config>

<tx:advice id="Second_txAdvice" transaction-manager="Second_TransactionManager">
    <tx:attributes>
        <tx:method name="*" propagation="REQUIRED" rollback-for="Exception" />
    </tx:attributes>
</tx:advice>

<aop:config>
    <aop:pointcut id="Second_daoimplOperation"
        expression="execution(* in.company.common.service.CommonServiceImpl.*(..))" />

    <aop:advisor advice-ref="Second_txAdvice" pointcut-ref="Second_daoimplOperation" />
</aop:config>

所有与数据库相关的服务都应该在匹配的切入点中,就像在这种情况下它是:in.company.common.service.CommonServiceImpl.*(..))

于 2014-04-11T08:05:02.567 回答
0

问题通过 AOP 解决。

  1. 定义多个数据源和相应的事务管理器(如我在基本问题中所示)
  2. First_dataSource 映射到 First_TransactionManager 和 Second_dataSource 映射到 Second_TransactionManager
  3. 根据您的业务规则选择以编程方式使用的数据源。就我而言,它是 orgId

    公共类 DataSourceProvider { @Autowired DataSource First_dataSource; @Autowired DataSource Second_dataSource;

        public DataSource getDataSource(int orgId) {
    
            if (orgId == Constants.BUSINESS_PARTY_1)
                return Second_dataSource;
            else
                return First_dataSource;
        }
    
        public DataSource getFirst_dataSource() {
            return First_dataSource;
        }
    
        public void setFirst_dataSource(DataSource First_dataSource) {
            First_dataSource = First_dataSource;
        }
    
        public DataSource getSecond_dataSource() {
            return Second_dataSource;
        }
    
        public void setSecond_dataSource(DataSource Second_dataSource) {
            Second_dataSource = Second_dataSource;
        }
    }
    
  4. AOP 配置:

于 2014-04-11T07:44:59.897 回答
0

考虑使用提供的 SpringAbstractRoutingDataSource而不是在多个事务管理器之间进行选择。这将是一个更清洁的解决方案。

在此处查看我对类似问题的回答:
https ://stackoverflow.com/a/44167079/2200690

于 2017-05-24T19:41:24.540 回答