Spring 引导路由数据源无法正常工作

Spring boot routing datasource not work correctly

我正在使用 Postgres、Hibernate、Atomikos、JPA 和 Thymeleaf 配置 spring 引导 Web 应用程序。 我使用 AbstractRoutingDataSource 路由到新数据源,如下所示:

    @Override
    protected Object determineCurrentLookupKey() {
            String currentTenantId = TenantContextHolder.getCurrentTenantId();

            // Get endpoint, database name from default database

            // New datasource
            DataSource dataSource = constructDataSource(setting, endpoint, databaseName);
            resolvedDataSourceMap.putIfAbsent(currentTenantId, dataSource);
            setTargetDataSources(resolvedDataSourceMap);
            afterPropertiesSet();

            return currentTenantId;

}

如果我打电话给

userRepository.countByUserId("aaa"); // This is custom method in my repository

,它路由并且 return 结果正确,但如果我调用

userRepository.findAll(); // My repository extends from SimpleJPARepository

,我总是得到以下错误(如果我再次调用,它会工作正常!) 请帮助我解释为什么以及我应该如何解决这个错误。

2018-03-24 12:03:47.566  INFO 17472 --- [nio-8080-exec-2] c.a.d.xa.XATransactionalResource         : 0000000002-pgxad: refreshed XAResource
2018-03-24 12:03:47.702 ERROR 17472 --- [nio-8080-exec-2] c.a.datasource.xa.XAResourceTransaction  : XA resource 'defaultDataSource-pgxad': prepare for XID '3139322E3136382E31372E3135352E746D313532313836373830313734343030303032:3139322E3136382E31372E3135352E746D32' raised -3: the XA resource detected an internal error

org.postgresql.xa.PGXAException: Error preparing transaction
    at org.postgresql.xa.PGXAConnection.prepare(PGXAConnection.java:309) ~[postgresql-42.2.1.jar:42.2.1]
    at com.atomikos.datasource.xa.XAResourceTransaction.prepare(XAResourceTransaction.java:384) ~[transactions-jta-4.0.6.jar:na]
    at com.atomikos.icatch.imp.PrepareMessage.send(PrepareMessage.java:40) [transactions-4.0.6.jar:na]
    at com.atomikos.icatch.imp.PrepareMessage.send(PrepareMessage.java:19) [transactions-4.0.6.jar:na]
    at com.atomikos.icatch.imp.PropagationMessage.submit(PropagationMessage.java:67) [transactions-4.0.6.jar:na]
    at com.atomikos.icatch.imp.Propagator$PropagatorThread.run(Propagator.java:63) [transactions-4.0.6.jar:na]
    at com.atomikos.icatch.imp.Propagator.submitPropagationMessage(Propagator.java:42) [transactions-4.0.6.jar:na]
    at com.atomikos.icatch.imp.ActiveStateHandler.prepare(ActiveStateHandler.java:171) [transactions-4.0.6.jar:na]
    at com.atomikos.icatch.imp.CoordinatorImp.prepare(CoordinatorImp.java:523) [transactions-4.0.6.jar:na]
    at com.atomikos.icatch.imp.CoordinatorImp.terminate(CoordinatorImp.java:687) [transactions-4.0.6.jar:na]
    at com.atomikos.icatch.imp.CompositeTransactionImp.commit(CompositeTransactionImp.java:282) [transactions-4.0.6.jar:na]
    at com.atomikos.icatch.jta.TransactionImp.commit(TransactionImp.java:172) [transactions-jta-4.0.6.jar:na]
    at com.atomikos.icatch.jta.TransactionManagerImp.commit(TransactionManagerImp.java:414) [transactions-jta-4.0.6.jar:na]
    at com.atomikos.icatch.jta.UserTransactionImp.commit(UserTransactionImp.java:86) [transactions-jta-4.0.6.jar:na]
    at org.springframework.transaction.jta.JtaTransactionManager.doCommit(JtaTransactionManager.java:1040) [spring-tx-5.0.4.RELEASE.jar:5.0.4.RELEASE]

...

Caused by: org.postgresql.util.PSQLException: ERROR: 準備されたトランザクションは無効です。
  Hint: max_prepared_transactionsを非ゼロに設定してください。

...

2018-03-24 12:03:47.715 ERROR 17472 --- [nio-8080-exec-2] c.a.datasource.xa.XAResourceTransaction  : XA resource '0000000002-pgxad': prepare for XID '3139322E3136382E31372E3135352E746D313532313836373830313734343030303032:3139322E3136382E31372E3135352E746D33' raised -3: the XA resource detected an internal error

org.postgresql.xa.PGXAException: Error preparing transaction
    at org.postgresql.xa.PGXAConnection.prepare(PGXAConnection.java:309) ~[postgresql-42.2.1.jar:42.2.1]
    at com.atomikos.datasource.xa.XAResourceTransaction.prepare(XAResourceTransaction.java:384) ~[transactions-jta-4.0.6.jar:na]

在同一个事务中访问2个数据库时出错。 因此,我需要通过 REQUIRE_NEW 创建新交易,如下所示:

@Transactional(propagation = Propagation.REQUIRES_NEW)
Tenant findByTenantId(Long tenantId);

或者,如@a_horse_with_no_name所说,"need to set max_prepared_transactions to something greater than the default of 0 in order to use 2phase commits and distributed transactions"。

感谢您的回复,@a_horse_with_no_name!