Использование Dropwizard и JDBI для запроса базы данных с несколькими схемами?
Я создаю Java Rest API с DropWizard (который использует JDBI), и мои требования состоят в том, что мне нужно запросить несколько схем MySQL с помощью одного и того же приложения. В основном это будет один экземпляр AWS MySQL, содержащий несколько схем - по одной схеме на клиента.
Мне нужен механизм, который знает, какую "схему" запрашивать в зависимости от запроса - IE: к какому клиенту относится запрос.
Я знаю, как создать источник данных, DAO и т. Д. (Используя это руководство: https://dropwizard.github.io/dropwizard/manual/jdbi.html), но не знаю, как сделать запрос к нескольким схемам.
Есть идеи?
2 ответа
Идеальный способ сделать это - захватить информацию, связанную со схемой, из запроса, сохранить ее в ThreadLocal и установить схему при каждом запросе соединения. К сожалению, когда я попробовал этот подход, я обнаружил, что метод setSchema еще не реализован в драйверах. Но я нашел другой способ (взломать), чтобы решить эту проблему. JDBI предоставляет оператор 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;
}
}
Это будет получать имя схемы при каждом запросе. Зарегистрируйте этот файл в загрузчике вашего приложения.
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. Это все. Вам не нужно беспокоиться о нескольких схемах.
Самое простое решение для вас будет использовать несколько:
@JsonProperty("database")
public DataSourceFactory getDataSourceFactory() {
return database;
}
Конфигурация так например:
@JsonProperty("products")
@JsonProperty("clients")
А затем файл конфигурации:
products:
# products schema configuration...
clients:
# clients configuration