Использование 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
Другие вопросы по тегам