AbstractRoutingDataSource无法在Spring Batch中工作

时间:2014-12-10 10:58:38

标签: spring routing spring-batch multi-tenant

我使用Spring Batch将大量数据从XML导入Oracle数据库。

我的应用程序是多租户知道的,每个租户可以拥有单独的数据库模式,或者几个租户也可以同时共享单个数据库模式。

从我的XML中,我获得了唯一的租户标识符,我将其用作租户数据库解析标识符,以便在运行时选择数据库。

我正在使用Spring MVC,hibernate。

我的XML

<users>
 <user>
    <userAccountDetail>
        <tenantId>acmebank</tenantId>
        <emailAddress>966019620abc5009254@6657170682.com</emailAddress>
    </userAccountDetail>
 </user>
</users>

我的春季批量配置

<batch:job id="walletUsersImportJob">
        <batch:step id="importUsers" allow-start-if-complete="true">
            <batch:tasklet>
                <batch:chunk reader="xmlItemReader" writer="userDetailWriter"
                    processor="userDetailProcessor" commit-interval="2147483647">
                </batch:chunk>
            </batch:tasklet>
            <batch:listeners>
                <batch:listener>
                    <bean
                        class="com.masterpass.datamigration.batch.core.listener.ItemFailureHandler" />
                </batch:listener>
            </batch:listeners>
        </batch:step>
    </batch:job>

数据源配置

<bean id="entityManagerFactory"
        class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="routingDataSource" />
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <property name="showSql" value="true" />
            </bean>
        </property>
</bean>



<bean id="routingDataSource"     
class="com.csam.wsc.enabling.tenant.jdbc.datasource.lookup.TenantRoutingDataSource"  >
        <property name="defaultTargetDataSource" ref="globalDataSource"/>
        <property name="tenantMetadataLookupStrategy" ref="tenantMetadataLookupStrategy" />
    </bean>

这里需要查找 tenantMetadataLookupStrategy 租户标识符,即作为XML的一部分收到的tenantId,我有一张类似

的地图

tenantId =数据源

acmebank = java:/ACMEBANK_DS
anybank = java:/ANYBANK_DS

这将为我提供用于任何DAO操作的数据库。

希望配置明智我很好。

让我告诉我的问题。

当Spring批处理应用程序引导时,org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource.determineTargetDataSource()调用哪个需要tenantID来识别目标数据源。

这个tenantID,我有XML格式,在ItemReader完成之前不可用。

使用 batch:tasklet 进行My Spring Batch配置,该配置在单个事务中围绕读取器,写入器和处理器。

由于上述原因,在引导期间我怀疑在初始化事务管理器时,entityManagerFactory会查找数据源,即routingDataSource,而这又需要tenantId。

我认为如果我从事务主体中删除读取器和处理器,我将获得一些捕获tenantId的位置并将其设置在某个上下文中,以便它可以在运行时选择DB。

即使我不想读者和处理器跨国意识如此之好如果我只能在交易中包装作家。

请建议。

1 个答案:

答案 0 :(得分:0)

这里有两件事:

  1. 要在Spring Batch中“从事务正文中删除读取和进程”几乎是不可能的。您必须重写TaskletStep(框架中最敏感的代码之一),我不建议这样做。
  2. 我认为您的路由数据源不起作用是正确的。话虽这么说,我实际上建议采用略有不同的方法。而不是使用路由数据源技术,为什么不使用ClassifierCompositeItemWriter?这会将路由向上移动一个级别(从连接到项目编写器),这允许每个编写器实例获得事务生命周期的连接。
  3. 您可以在此处详细了解javadoc中的ClassifierCompositeItemWriterhttp://docs.spring.io/spring-batch/trunk/apidocs/org/springframework/batch/item/support/ClassifierCompositeItemWriter.html