【问题标题】:Switching between read-only and read-write databases using spring @Transactional and AbstractRoutingDataSource使用 spring @Transactional 和 AbstractRoutingDataSource 在只读和读写数据库之间切换
【发布时间】:2020-11-20 00:29:25
【问题描述】:

我需要使用Spring的@Transactional注解来使用只读和读写数据源。我有以下设置:

public class DataSourceRouter extends AbstractRoutingDataSource {
    @Override
    protected Object determineCurrentLookupKey() {
        return DatabaseContextHolder.getEnvironment();
    }
}

@Aspect
public class DataSourceSwitch {
    @Around("@annotation(transactional)")
    public Object proceed(ProceedingJoinPoint pjp, Transactional transactional) throws Throwable {
        DatabaseEnvironment newEnv = transactional.readOnly() ?
                DatabaseEnvironment.READ_ONLY : DatabaseEnvironment.READ_WRITE;
        DatabaseContextHolder.setEnvironment(newEnv);
        return pjp.proceed();
    }
}

@Configuration
@EnableTransactionManagement
@EnableAspectJAutoProxy
public class JpaConfig {
    @Bean
    @Primary
    public DataSource getDataSource() throws Exception {
        DataSourceRouter router = new DataSourceRouter();
        Map<Object, Object> dataSources = new HashMap<>();
        dataSources.put(DatabaseEnvironment.READ_ONLY, <readOnlyDb>);
        dataSources.put(DatabaseEnvironment.READ_WRITE, <readWriteDb>);
        router.setTargetDataSources(dataSources);
        return router;
    }
}

DatabaseContextHolder 类将应使用的 DB 保存到 ThreadLocal。带有@Transactional 注释的方法会相应地设置readOnly 标志。

我面临的问题是路由器的方法determineCurrentLookupKey在调用第一个@Transactional方法时只调用一次,并且在以下事务方法中不会再次调用,这可能需要不同的数据源.例如,如果调用的第一个方法需要一个只读数据源,然后另一个方法需要一个读写数据源,则 DB 上下文确实会发生变化,但不会再次调用 determineCurrentLookupKey,因此它会尝试写入 read-只有数据库,并且失败。每次调用事务方法时不应该调用determineCurrentLookupKey方法吗?

这些方法不是相互调用的,也不是从同一个类调用的。将propagation = Propagation.REQUIRES_NEW 添加到@Transactional 注释也没有帮助。让它发挥作用的最佳方法是什么?

【问题讨论】:

    标签: java spring-data-jpa spring-transactions


    【解决方案1】:

    解决方案是将其添加到application.yaml:

    spring:
      jpa:
        open-in-view: false
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-01-26
      • 1970-01-01
      • 2010-12-09
      • 2020-02-26
      • 2013-04-08
      • 1970-01-01
      • 2019-09-17
      • 2017-09-06
      相关资源
      最近更新 更多