如何在Spring的单个事务中使用多个数据源(一个用于读取,另一个用于写入)?

时间:2019-01-09 08:08:57

标签: java spring hibernate

我已经配置了两个数据库。一个用于读取(只读),另一个用于读写操作。我的服务涉及读和写操作。我想将只读数据库用于所有读取操作,将其他数据库用于写入操作。我如何通过Spring交易实现这一目标。我已经实现了基于注释的方法,该方法使用AbstractRoutingDataSource更改了数据源。但是,每次我需要使用propogation = Requires_New创建一个新的转换时。有更好的方法吗?

@DbSource(DbType.READ_REPLICA)
@Transactional(propogation=Requires_New)
public Object readData(long id) {
   return dataDao.find(id);
}

1 个答案:

答案 0 :(得分:0)

您应该为两个数据存储以及TransactionManager bean创建单独的spring配置。这些bean中至少有一个应该具有name的值,以便您可以在需要时使用适当的事务管理器:

@Transactional(transactionManager="DS1transactionManagerBeanName")
// DS1dataStoreRelevant class/method

当然,JpaTransactionManager不可能在单个事务中使用两个数据存储区的组合逻辑。如果这是您要寻找的内容,则应考虑使用由Web容器(如IBM WebSphere或其他容器,如Atomikos / Bitronix等)提供的分布式JtaTransactionManager,它为您提供了不同数据存储之间的事务性(通常是XA资源)。

在某些情况下(例如Oracle数据存储),一些可能的解决方法是提供从一个数据库到另一个数据库的可见性,并使用单个数据存储/事务管理器,但我不确定它在数据库方面如何工作。

最基本的解决方案是不混合影响每个数据存储的逻辑并将其安排在顺序事务中,但是由于上述整个操作链本身都不是跨国的,因此可能的回滚仅适用于当前事务(否回滚到之前提交的内容)。引入一些带有脏标志等的回滚/重试策略将需要一些额外的逻辑。