RoutingDataSource 不在事务上切换上下文

RoutingDataSource is not switching context on transactions

我正在尝试使用 spring class 实现数据库 read/write 分离(我使用了本教程)

AbstractRoutingDataSource

我正在处理的应用程序正在使用多线程和连接池 (hikari)。所以我为每个租户创建了一个(master/replica 数据源)

这就是我创建数据源的方式

public DataSource RoutingDatasource(String tenantId, 字符串 databaseMasterUrl, 字符串 databaseReplicaUrl, 字符串用户, 字符串密码){ final RoutingDataSource routingDataSource = new RoutingDataSource();

    final DataSource masterDataSource = buildTargetDataSource(tenantId,
        cachePrepStmtsValue,
        prepStmtCacheSize,
        prepStmtCacheSqlLimit,
        databaseMasterUrl,
        driverClass,
        user,
        password,
        MASTER_DATASOURCE_PREFIX);
    final DataSource replicaDataSource = buildTargetDataSource(poolName + tenantId,
        cachePrepStmtsValue,
        prepStmtCacheSize,
        prepStmtCacheSqlLimit,
        databaseReplicaUrl,
        driverClass,
        user,
        password,
        REPLICA_DATASOURCE_PREFIX);
    final Map<Object, Object> targetDataSources = new HashMap<>();
    targetDataSources.put(DbContext.DbType.MASTER, masterDataSource);
    targetDataSources.put(DbContext.DbType.REPLICA, replicaDataSource);
    routingDataSource.setTargetDataSources(targetDataSources);
    routingDataSource.setDefaultTargetDataSource(masterDataSource);
    routingDataSource.afterPropertiesSet();
    return routingDataSource;
}

上下文是这样决定的

  public class RoutingDataSource extends AbstractRoutingDataSource {
        @Override
        protected Object determineCurrentLookupKey() {
            return DbContext.getDbType();

        }

这就是我告诉事务切换上下文的方式

  @Transactional(readOnly = true)
    public Opportunite consulter(UUID personUuid) {
      DbContext.setDbType(DbContext.DbType.REPLICA);
        //some work
        DbContext.reset();
        return some_result ;
    }

代码编译正常,但并未真正切换上下文。事实上,在调试之后,问题是在设置事务之前请求了数据源。当事务最终设置时,为时已晚,数据源已经加载。

我该如何解决这个问题?谢谢。

为了解决这个问题,我必须在进入事务之前定义要使用的数据库,我已经定义了一个过滤器(我正在使用 spring)

public class DbFilter extends  {
//les urls that do not only GET method
private final static String NOT_ONLY_GET_URL= "/api/parametre";

@Override
protected void doFilterInternal(HttpServletRequest request,
                                HttpServletResponse response,
                                FilterChain filterChain) throws IOException, ServletException, RestException {
    DbContext.setDbType(DbContext.DbType.MASTER);
    if (!NOT_ONLY_GET_URL.equals(request.getRequestURI()) && request.getMethod().equals("GET")) {
        DbContext.setDbType(DbContext.DbType.REPLICA);
    }
    filterChain.doFilter(request, response);
}

此方法在调用任何@transactional 方法之前运行,如果是GET 方法则正在切换数据库。

我已经删除了 DbContext.setDbType(DbContext.DbType.REPLICA);和@transactional方法中的Dbcontext.reset()。

"not only get urls parts" 之所以被定义,是因为在我的应用程序中有一些 get 方法在内部进行更新,所以我检测到这些 url 并将它们影响到主数据库。