使用 Dropwizard 和 JDBI 查询具有多个模式的数据库?
Using Dropwizard & JDBI to query database with multiple schemas?
我正在使用 DropWizard(使用 JDBI)构建 Java Rest API,我的要求是我需要使用同一应用程序查询多个 MySQL 模式。它基本上是一个 AWS MySQL 实例,其中包含多个模式——每个客户端一个模式。
我需要的是一种机制,它知道根据请求查询哪个 "schema" -- 即:请求属于哪个客户端。
我知道如何创建数据源、DAO 等(使用本教程:https://dropwizard.github.io/dropwizard/manual/jdbi.html)但不知道如何查询多个模式。
有什么想法吗?
最简单的解决方案是使用多个:
@JsonProperty("database")
public DataSourceFactory getDataSourceFactory() {
return database;
}
配置例如:
@JsonProperty("products")
@JsonProperty("clients")
然后是配置文件:
products:
# products schema configuration...
clients:
# clients configuration
实现此目的的理想方法是,从请求中捕获模式相关信息并将其保存在 ThreadLocal 中,并在请求连接时设置模式。
不幸的是,当我尝试这种方法时,我发现 setSchema 方法尚未在驱动程序中实现。但我找到了另一种方法(hack)来解决这个问题。
JDBI提供了statement Locator,我们可以在这里使用它来解决这个问题。
假设我们在查询参数中发送架构名称,我们可以使用球衣请求过滤器来获取架构名称。
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;
}
}
这将在每次请求时获取架构名称。在您的应用程序中注册此文件管理器 bootstrap.
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;
}
}
假设我们想要访问所有模式中的 table "users",像这样编写查询。
@OverrideStatementLocatorWith(SchemaReWriter.class)
public interface UserDao {
@SqlQuery("select * from :schema.users")
public List<User> getAllUsers();
}
不要忘记用 StatementRewriter 注释 Dao。就这样。您无需担心多个架构。
我正在使用 DropWizard(使用 JDBI)构建 Java Rest API,我的要求是我需要使用同一应用程序查询多个 MySQL 模式。它基本上是一个 AWS MySQL 实例,其中包含多个模式——每个客户端一个模式。
我需要的是一种机制,它知道根据请求查询哪个 "schema" -- 即:请求属于哪个客户端。
我知道如何创建数据源、DAO 等(使用本教程:https://dropwizard.github.io/dropwizard/manual/jdbi.html)但不知道如何查询多个模式。
有什么想法吗?
最简单的解决方案是使用多个:
@JsonProperty("database")
public DataSourceFactory getDataSourceFactory() {
return database;
}
配置例如:
@JsonProperty("products")
@JsonProperty("clients")
然后是配置文件:
products:
# products schema configuration...
clients:
# clients configuration
实现此目的的理想方法是,从请求中捕获模式相关信息并将其保存在 ThreadLocal 中,并在请求连接时设置模式。 不幸的是,当我尝试这种方法时,我发现 setSchema 方法尚未在驱动程序中实现。但我找到了另一种方法(hack)来解决这个问题。 JDBI提供了statement Locator,我们可以在这里使用它来解决这个问题。
假设我们在查询参数中发送架构名称,我们可以使用球衣请求过滤器来获取架构名称。
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;
}
}
这将在每次请求时获取架构名称。在您的应用程序中注册此文件管理器 bootstrap.
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;
}
}
假设我们想要访问所有模式中的 table "users",像这样编写查询。
@OverrideStatementLocatorWith(SchemaReWriter.class)
public interface UserDao {
@SqlQuery("select * from :schema.users")
public List<User> getAllUsers();
}
不要忘记用 StatementRewriter 注释 Dao。就这样。您无需担心多个架构。