как установить локальную переменную для транзакции в JDBC - PullRequest
0 голосов
/ 02 ноября 2018

Я работаю над проектом, в базе данных которого мне нужно инициализировать переменную сеанса. Если я работаю напрямую с sql, инициализация выполняется с SET оператором

set local app.user_id to "0000";

Я пытаюсь инициализировать его с Connection#setClientInfo(), но не удалось

try(Connection connection = getDataSource().getConnection()) {
    boolean isAutoCommit = connection.getAutoCommit();
    try {
        Properties properties = new Properties();
        properties.put("app.user_id", "0000");

        connection.setAutoCommit(false);
        connection.setClientInfo(properties);

        String query = "insert into positions (name, description) values (?, ?)";

        try(PreparedStatement statement = connection.prepareStatement(query)) {
            statement.setString(1, position.getName());
            statement.setString(2, position.getDescription());

            statement.executeUpdate();
        }

        connection.commit();
    }
    catch (SQLException e) {
        e.printStackTrace();
        connection.rollback();
    }
    finally {
        connection.setAutoCommit(isAutoCommit);
    }
}

Я получаю PSQLException (запрос вставки зависит от параметра и не проходит)

org.postgresql.util.PSQLException: ERROR: unrecognized configuration parameter "app.user_id"

Если я использую PreparedStatement, я получаю PSQLException с сообщением ОШИБКА: синтаксическая ошибка в или около "$ 1"

try(Connection connection = getDataSource().getConnection()) {
    boolean isAutoCommit = connection.getAutoCommit();
    try {
        connection.setAutoCommit(false);
        try(PreparedStatement statement = connection.prepareStatement("set local app.user_id to ?")) {
            statement.setString(1, "0000");
            statement.execute();
        }

        String query = "insert into positions (name, description) values (?, ?)";

        try(PreparedStatement statement = connection.prepareStatement(query)) {
            statement.setString(1, position.getName());
            statement.setString(2, position.getDescription());

            statement.executeUpdate();
        }

        connection.commit();
    }
    catch (SQLException e) {
        e.printStackTrace();
        connection.rollback();
    }
    finally {
        connection.setAutoCommit(isAutoCommit);
    }
}

Единственный способ пройти - это напрямую выполнить запрос с фиксированными значениями. Но при этом я вынужден использовать конкатенацию для построения запроса. И я не хочу этого делать.

try(Connection connection = getDataSource().getConnection()) {
    boolean isAutoCommit = connection.getAutoCommit();
    try {
        connection.setAutoCommit(false);
        try(Statement statement = connection.createStatement()) {
            statement.execute("set local app.user_id to 0000");
        }

        String query = "insert into positions (name, description) values (?, ?)";

        try(PreparedStatement statement = connection.prepareStatement(query)) {
            statement.setString(1, position.getName());
            statement.setString(2, position.getDescription());

            statement.executeUpdate();
        }

        connection.commit();
    }
    catch (SQLException e) {
        e.printStackTrace();
        connection.rollback();
    }
    finally {
        connection.setAutoCommit(isAutoCommit);
    }
}

Как правильно инициализировать такие параметры? Я использую PostgreSQL 11, JDBC 4.2 (с драйвером 42.2.5) и DBCP 2.5

Редактировать

Я сделал это, позвонив set_config.

try(PreparedStatement statement = connection.prepareStatement("select set_config(?, ?, true)")) {
    statement.setString(1, "app.user_id");
    statement.setString(2, "0000");

    statement.execute();
}

Но вопрос остается. Как позвонить SET в JDBC

1 Ответ

0 голосов
/ 02 ноября 2018

Я думаю, вам нужно сделать это на DataSource, а не на Connection.

В postgresql единственный способ, которым я знаю, - это преобразование с понижением частоты. Что-то вроде:

DataSource myDS = getDataSource();
if (DataSource instanceof BaseDataSource.class) {
    BaseDataSource pgDS = (BaseDataSource) myDS;   // expose setProperty method
    pgDS.setProperty("app.user_id", "0000");
}

где вы разместите это в вашем заявлении, очевидно, зависит от многих деталей, не представленных в вашем вопросе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...