如何在多租户 spring 引导程序中使用事务拦截器?

How to use transaction interceptor in a multi-tenant spring boot program?

我有一个 Spring Boot 2 + Hibernate 5 多租户应用程序,它连接到多个 oracle 数据库。当我使用 JpaRepository 时,一切正常,即在收到 http 请求后,'Interceptor' 检测到数据源并且 'MultiTenantConnectionProvider' 实现选择正确的数据源供 TransactionManager 使用。 问题是什么? 我想使用 TransactionInterceptor 来处理来自特定 bean(扩展 JdbcDaoSupport 或注入 JdbcDaoSupport 实现)的某些方法(带有方法名称)的事务。对不起,如果我解释得有点混乱。 但是对于每个 http 请求,该 bean 的数据源是不可变的(默认数据源)。而注入的存储库在正确的事务中对正确的数据源进行操作。

<bean id="txProxyTemplate" abstract="true"
          depends-on="transactionManager"
          class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
        <property name="transactionManager">
            <ref bean="transactionManager" />
        </property>
        <property name="transactionAttributes">
            <props>
                <prop key="save*">PROPAGATION_REQUIRED,-Exception</prop>
            </props>
        </property>
</bean>
<bean id="genericJdbcDao" parent="txProxyTemplate">
        <property name="target">
            <bean class="org.broker.dao.impl.BaseGenericJdbcDAOImpl">
                <property name="jdbcTemplate" ref="jdbcTemplate"/>
            </bean>
        </property>
</bean>

谁能帮忙解决这个问题?

我终于解决了这个问题。按照代码部分:

@Bean("jdbcTemplate")
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public JdbcTemplate jdbcTemplate(
        @Qualifier("tenantIdentifierResolver") TenantIdentifierResolverImpl tenantResolver,
        @Qualifier("tenantConnectionProvider") DataSourceMultiTenantConnectionProviderImpl dataSourceProvider) {
    return new RhaJdbcTemplate(dataSourceProvider.selectDataSource(tenantResolver.resolveCurrentTenantIdentifier()));
}

@Bean(value = "transactionInterceptor")
public TransactionInterceptor transactionInterceptor(
        @Qualifier("txProxyTemplateConfig") Properties txProxyTemplateConfig,
        @Qualifier("transactionManager") PlatformTransactionManager transactionManager) {
    TransactionInterceptor transactionInterceptor = new TransactionInterceptor();
    transactionInterceptor.setTransactionAttributes(txProxyTemplateConfig);
    transactionInterceptor.setTransactionManager(transactionManager);
    return transactionInterceptor;
}

@Bean("genericJdbcDAO")
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public ProxyFactoryBean genericJdbcDAO(
        @Qualifier("jdbcTemplate") JdbcTemplate jdbcTemplate) throws ClassNotFoundException {
    BaseGenericJdbcDAOImpl genericJdbcDAO = new BaseGenericJdbcDAOImpl();
    genericJdbcDAO.setJdbcTemplate(jdbcTemplate);
    ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean();
    proxyFactoryBean.setTarget(genericJdbcDAO);
    proxyFactoryBean.setProxyInterfaces(new Class[] {BaseGenericJdbcDAO.class});
    proxyFactoryBean.setInterceptorNames("transactionInterceptor");
    return proxyFactoryBean;
}

然后将BaseGenericJdbcDAO注入controller,作为示例:

@RestController
public class VoucherLineRest {
    @Resource(name = "genericJdbcDAO")
    private BaseGenericJdbcDAO genericJdbcDAO;
}

您会看到对于每个请求都选择了正确的数据源,并且 TransactionInterceptor 拦截从 BaseGenericJdbcDAO bean 调用的每个方法并应用正确的交易传播。

希望您喜欢这次体验。