Пользователи приложений в политиках на уровне строк: как установить переменные сеанса

Я пытаюсь написать политики на уровне строк, которые проверяют права пользователя перед выполнением запросов. В этом контексте мне нужно иметь возможность устанавливать переменную сеанса, содержащую идентификатор пользователя, когда соединение выбирается из пула соединений, и отменять / освобождать эту же переменную сеанса, когда соединение возвращается обратно в пул. Следующий блог может дать хороший фон, чтобы объяснить, что я пытаюсь сделать: https://blog.2ndquadrant.com/application-users-vs-row-level-security/

В моей настройке у меня есть следующие слои:

  1. Хикари: HikariDataSource
  2. Весна: TransactionAwareDataSourceProxy (используя источник данных Hikari), DataSourceTransactionManager (используя источник данных Hikary)
  3. jOOQ: DataSourceConnectionProvider (используя источник данных Spring), DefaultDSLContext

Первые два слоя только внутренние. То есть все запросы в приложении выполняются через последний уровень jOOQ.

Итак, мне нужно иметь возможность реализовать обратный вызов при подключении take from pool а также give back to pool,

Я просматривал документацию по Hikari и Spring, но не смог найти ничего полезного. Вероятно, это мой первый вопрос: предоставляют ли Hikari и / или Spring такие обратные вызовы?

Следующим шагом в моем расследовании был JOOQ. Я наткнулся на ExecuteListener, Это мой дополнительный вопрос: будет ExecuteListener быть хорошим приложением для этого? Это не реализует фактическую точку, когда соединение взято и возвращено, но execution context вероятно, достаточно хорош в моем случае (так как все мои запросы выполняются в jOOQ)? Если это так, я должен реализовать start а также end функции?

1 ответ

Решение

Это можно решить на разных уровнях вашего текущего стека. Вот два предложения:

Решая это в DataSource / Connection полномочие

Большинство пулов соединений реализуют следующую семантику:

  • DataSource.getConnection(): "Возьми из пула"
  • Connection.close(): "Отдай обратно в бассейн"

Таким образом, вы можете проксировать эти два API и реализовать желаемую семантику внутри этих соответствующих методов. Это немного больше работы, но она будет работать с любым клиентом JDBC, включая jOOQ (т.е. он также будет работать, когда вы не используете jOOQ)

Решая это в JOOQ

Если все ваши взаимодействия с базой данных проходят через jOOQ, вы можете решить эту проблему проще с помощью jOOQ напрямую, используя ConnectionProvider SPI, который содержит два метода, которые имеют именно ту семантику, которая вам требуется:

  • ConnectionProvider.acquire()
  • ConnectionProvider.release(Connection)

Таким образом, вместо использования JOOQ "из коробки" DataSourceConnectionProvider Вы могли бы сделать это:

public class MyConnectionProvider implements ConnectionProvider {

    // Configure spring to inject your data source here
    @Autowire
    DataSource ds;

    @Override
    public Connection acquire() {
        try {
            Connection c = ds.getConnection();
            // Do your stuff here
            return c;
        }
        catch (SQLException e) {
            throw new DataAccessException("Something failed", e);
        }
    }

    @Override
    public void release(Connection c) {
        try {
            // Do your stuff here
            c.close();
        }
        catch (SQLException e) {
            throw new DataAccessException("Something failed", e);
        }
    }
}

Вы могли бы сделать это с ExecuteListener тоже, но вышеуказанный подход, конечно, проще.

Другие вопросы по тегам