Алиса и Боб хотят, чтобы Дэйв разработал приложение. Оба хотят работать с идентичными типами данных, но оба хотят сохранить свои данные отдельно и безопасными. Поэтому Дейв уходит, чтобы построить схему DEV.Dynamic runtime Выбор схемы PostgreSQL в jOOQ
CREATE TABLE foo (id INT PRIMARY KEY);
CREATE FUNCTION bar(_id INT) RETURNS INT AS $$
INSERT INTO foo (id) VALUES (_id) RETURNING id;
$$ LANGUAGE SQL;
Дэйв использует пролетный путь для инициализации схемы для Алисы и Боба, поэтому они оба имеют таблицу Foo и функцию бара. Дэйв использует jOOQ для генерации java-api и сопоставляет схему DEV во время выполнения с пользовательскими схемами. Дейв, ранее не имеющий отношения ни к одному из своих клиентов, внезапно оказывается племянником Боба.
Но Алиса и Боб возвращаются к Дейву позже и попросят его написать для них автоматизацию. Поэтому Дейв решает создать машинного пользователя Роба, который имеет доступ к схемам Алисы и Боба. Он может повторно использовать все тот же код, сгенерированный jOOQ, и все, что использует foo, работает безупречно, пока автоматизация не попытается выполнить функцию бара - Ошибка: отношение «foo» не существует. Отображение схемы времени выполнения не влияет на ссылку, не содержащую схемы, на foo внутри функциональной панели.
Тривиальный ответ заключается в том, чтобы установить путь search_path к тому, какой пользователь Rob должен маскироваться как. Это можно установить вручную перед каждым набором вызовов jOOQ, но это похоже на тип подверженного ошибкам, утомительный код jOOQ, как правило, изолирует нас от записи. Дэйв мог создать двух пользователей Rolice и Robob, каждый из которых индивидуально настроен для доступа к своему соответствующему клиенту. Но это, очевидно, плохо масштабируется, особенно при использовании пула соединений. Дэйв выбирает настраиваемый ConnectionProvider, который задает путь search_path, но это потенциально ужасно много накладных расходов, так как запрос search_path должен возвращать результат перед возвратом соединения.
Так что Дэйв охотится вокруг, задает очевидный вопрос о StackOverflow о настройке пути search_path и узнает, что функция была удалена по отличным причинам из jOOQ во время выпуска 3.0. Но Дэйв - тот парень, который действительно любит элегантность jOOQ и чувствует, что должно быть лучшее решение, чем его взломать.
Я не Дэйв, но я, конечно, вижу, откуда он. Каков наилучший способ в jOOQ, чтобы один автоматизированный пользователь взаимодействовал с несколькими идентичными пользовательскими схемами и, в частности, с функциями, содержащими ссылки без схемы?
В случае, если это имеет значение, я на PostgreSQL 9.3 и jOOQ 3.5. Дэйв находится на том, кем бы вы его ни хотели, так как я сделал его полчаса назад.
Соответствующий бит решения ConnectionProvider:
@Override
public Connection acquire() throws DataAccessException {
Connection c = dataSource.getConnection();
try(Statement s = c.createStatement()){
s.execute("SET search_path = '"+schema+"'");
}catch(SQLException e){
throw new DataAccessException("Could not initialize connection", e);
}
return c;
}
Я не получаю эту часть: «*, поскольку запрос search_path должен возвращать результат перед возвратом соединения *» - не можете ли вы просто запустить 'set schema = ...' (или 'set search_path = ...'), например, как «родной» оператор в «ConnectionProvider»? W hy нужно ли запускать * запрос *? –
@a_horse_with_no_name, JDBC не имеет асинхронного выполнения, поэтому каждый раз, когда jOOQ запрашивает соединение, он должен ждать, пока сервер ответит OK, чтобы установить путь search_path. Он не возвращает ResultSet, но возвращает результат. Может быть, я не понимаю, что вы подразумеваете под «родной»? – Fuwjax
Что вы используете для управления транзакциями? Я считаю, что правильное место для инициализации пути поиска - это начало транзакции ... Ваше текущее решение слишком часто устанавливает путь поиска, я думаю –