【问题标题】:Using Dropwizard & JDBI to query database with multiple schemas?使用 Dropwizard 和 JDBI 查询具有多个模式的数据库?
【发布时间】:2015-05-28 20:20:31
【问题描述】:

我正在使用 DropWizard(它使用 JDBI)构建一个 Java Rest API,我的要求是我需要使用同一个应用程序查询多个 MySQL 模式。它基本上是一个包含多个模式的 AWS MySQL 实例——每个客户端一个模式。

我需要的是一种机制,它知道根据请求查询哪个“模式”——即:请求属于哪个客户端。

我知道如何创建数据源、DAO 等(使用本教程:https://dropwizard.github.io/dropwizard/manual/jdbi.html)但不知道如何查询多个模式。

有什么想法吗?

【问题讨论】:

  • 所有模式都有相同的表吗?或不同的架构有差异表
  • 所有模式都有相同的表。

标签: java mysql dropwizard jdbi multiple-schema


【解决方案1】:

理想的方法是,从请求中捕获架构相关信息并将其保存在 ThreadLocal 中,并在请求连接时设置架构。 不幸的是,当我尝试这种方法时,我发现 setSchema 方法尚未在驱动程序中实现。但我找到了另一种方法(hack)来解决这个问题。 JDBI 提供了语句定位器,我们可以在这里使用它来解决这个问题。

假设我们在查询参数中发送模式名称,我们可以使用 jersey 请求过滤器来获取模式名称。

public class Schema {
    public static ThreadLocal<String> name = new ThreadLocal<>();
}


public class SchemaNameFilter implements ContainerRequestFilter {

    @Override
    public ContainerRequest filter(ContainerRequest request) {
        if(request.getQueryParameters().containsKey("schema")) {
            Schema.name.set(request.getQueryParameters().get("schema").get(0));
        }
        return request;
    }
}

这将获取每个请求的架构名称。在您的应用程序引导程序中注册此文件管理器。

environment.jersey().property(ResourceConfig.PROPERTY_CONTAINER_REQUEST_FILTERS, asList(new SchemaNameFilter()));

现在我们需要编写第二部分,我们应该在其中使用此架构信息。包括这个 SchemaRewriter,

public class SchemaReWriter implements StatementLocator {
    @Override
    public String locate(String sql, StatementContext ctx) throws Exception {
        if (nonNull(Schema.name.get())) {
            sql = sql.replaceAll(":schema", Schema.name.get());
        }
        return sql;
    }
}

假设我们要访问所有模式中的“用户”表,这样编写查询。

@OverrideStatementLocatorWith(SchemaReWriter.class)
public interface UserDao {

  @SqlQuery("select * from :schema.users")
  public List<User> getAllUsers();

}

不要忘记使用 StatementRewriter 注释 Dao。就这样。您无需担心多个架构。

【讨论】:

  • 非常感谢!我现在用你的例子让它工作了:)
【解决方案2】:

对您来说最简单的解决方案是使用多个:

  @JsonProperty("database")
    public DataSourceFactory getDataSourceFactory() {
        return database;
    }

配置例如:

@JsonProperty("products")
@JsonProperty("clients")

然后是配置文件:

products:
  # products schema configuration...
clients:
  # clients configuration

【讨论】:

  • 感谢您的努力,但这并不能解决我的问题。我只有一个需要连接的 AWS MySQL RDMS 实例,但在该实例中,我将拥有多个具有相同架构的数据库。我的应用程序需要一种根据请求选择要查询的架构的方法。
  • 啊抱歉...我错过了...您是否预先了解客户,因为您可以为他们创建数据源?如果是 - 我的方法仍然有效(或其他类似 Spring JDBC)。如果不是,那么这可能有点棘手 - 因为我认为您不能依赖 Dropwizard 开箱即用的事务处理,因为它需要您在应用程序开始时设置 DataSources(据我所知) .所以在这种情况下,我会说你需要实现一些较低级别的逻辑(比如使用 c3p0 的连接池和一些手动的基本事务管理 - @UnitOfWork 在这种情况下不起作用)。
  • 如果你有固定数量的数据库,那么你仍然可以使用这种方法,并将 DAO 的映射传递给你的类,你可以根据请求选择它。但如果它是动态更改数据库集,那么 dropwizard 的 JDBI 模块可能不够灵活。然后,您可以直接使用 JDBI 并编写自己的自定义连接池管理,或者您可以将数据库设计更改为只有一个但在所有表中都有特定的“标识符”列。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-11-25
  • 2014-07-26
  • 2010-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-22
相关资源
最近更新 更多