首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >RoutingDataSource没有在事务上切换上下文

RoutingDataSource没有在事务上切换上下文
EN

Stack Overflow用户
提问于 2019-08-28 14:31:11
回答 2查看 482关注 0票数 0

我正在尝试使用spring类实现数据库读写分离(我使用了本教程)。

AbstractRoutingDataSource

我正在使用的应用程序是使用多值和连接池(hikari)。因此,我为每个租户创建了一个(主/副本数据源)

我就是这样创建数据源的

公共DataSource RoutingDatasource(String tenantId,String databaseMasterUrl,String databaseReplicaUrl,String user,String password) { RoutingDataSource routingDataSource =新RoutingDataSource();

代码语言:javascript
运行
复制
    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;
}

这就是如何确定上下文的方法。

代码语言:javascript
运行
复制
  public class RoutingDataSource extends AbstractRoutingDataSource {
        @Override
        protected Object determineCurrentLookupKey() {
            return DbContext.getDbType();

        }

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

代码语言:javascript
运行
复制
  @Transactional(readOnly = true)
    public Opportunite consulter(UUID personUuid) {
      DbContext.setDbType(DbContext.DbType.REPLICA);
        //some work
        DbContext.reset();
        return some_result ;
    }

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

我怎么才能纠正这种行为?谢谢。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-11-06 09:11:58

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

代码语言:javascript
运行
复制
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);
}

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

我删除了@事务性方法中的DbContext.setDbType(DbContext.DbType.REPLICA);和Dbcontext.reset()。

定义“不仅是获取urls部件”只是因为在我的应用程序中有一些get方法在内部进行更新,因此我检测到了这些urls,并将它们影响到主数据库。

票数 0
EN

Stack Overflow用户

发布于 2022-08-16 03:05:44

spring.jpa.open-in-view设置为false

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57694764

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档