Advertisement
avengerbot

MyBatis Interceptor Example

Mar 21st, 2025 (edited)
343
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 4.93 KB | Source Code | 0 0
  1. package my.example.mybatis.handler;
  2.  
  3. import org.apache.ibatis.executor.statement.StatementHandler;
  4. import org.apache.ibatis.mapping.BoundSql;
  5. import org.apache.ibatis.plugin.Interceptor;
  6. import org.apache.ibatis.plugin.Intercepts;
  7. import org.apache.ibatis.plugin.Invocation;
  8. import org.apache.ibatis.plugin.Signature;
  9.  
  10. import java.sql.Connection;
  11. import java.sql.Statement;
  12.  
  13. @Intercepts({
  14.         @Signature(
  15.                 type = StatementHandler.class,
  16.                 method = "prepare",             // "prepare" - стадия подготовки запроса (из StatementHandler)
  17.  
  18.                 args = {                        // StatementHandler#prepare(
  19.                         Connection.class,       //     Connection connection,
  20.                         Integer.class           //     Integer transactionTimeout
  21.                                                 // )
  22.                 }
  23.         )
  24. })
  25. public class DynamicQueryParamInterceptor implements Interceptor {
  26.  
  27.     // Если не работаем с динамикой, то можем использовать просто константу
  28.     private static final String DYNAMIC_QUERY_PARAM = "value";
  29.  
  30.     @Override
  31.     public Object intercept(Invocation invocation) throws Throwable {
  32.         // Какие именно у нас есть аргументы - смотрим в @Signature#args
  33.         final Connection connection = (Connection) invocation.getArgs()[0];
  34.  
  35.         // 1. Получение аргументов из вызова
  36.         final String dynamicQueryParam = getDynamicQueryParam(invocation);
  37.         // Используем SET setting = %s для Clickhouse
  38.         final String dynamicQueryParamQuery = "SET setting TO %s".formatted(dynamicQueryParam);
  39.  
  40.         // 2. Получение постоянного значения
  41.         final String dynamicQueryParamConstant = DYNAMIC_QUERY_PARAM;
  42.         // Используем SET setting = %s для Clickhouse
  43.         final String dynamicQueryParamConstantQuery = "SET setting TO %s".formatted(dynamicQueryParamConstant);
  44.  
  45.         // 3. Получение параметра из холдера контекста запроса
  46.         final String dynamicQueryParamContext = getDynamicQueryParamThreadLocal();
  47.         // Используем SET setting = %s для Clickhouse
  48.         final String dynamicQueryParamContextQuery = "SET setting TO %s".formatted(dynamicQueryParamContext);
  49.  
  50.         try (final Statement statement = connection.createStatement()) {
  51.             statement.execute("dynamicQueryParam");
  52.         }
  53.         return invocation.proceed();
  54.     }
  55.  
  56.     // Необязательный метод
  57.     @Override
  58.     public Object plugin(Object target) {
  59.         // Оборачиваем целевой объект в интерсептор
  60.         return Plugin.wrap(target, this);
  61.     }
  62.  
  63.     // Необязательный метод
  64.     @Override
  65.     public void setProperties(Properties properties) {
  66.         // Можем так же читать свойства из конфигурации
  67.         this.setting = properties.getProperty("setting", "default_value");
  68.     }
  69.  
  70.     // 1. Получение аргументов из вызова (модель)
  71.     private String getDynamicQueryParam(Invocation invocation) {
  72.         final BoundSql boundSql = (BoundSql) invocation.getTarget();
  73.         final Object parameterObject = boundSql.getParameterObject();
  74.         if (parameterObject instanceof SomeParams someParams) {
  75.             return someParams.getValue();
  76.         }
  77.         // Или любое другое значение по дефолту
  78.         return null;
  79.     }
  80.  
  81.     // 3. Получение параметра из холдера контекста запроса
  82.     private String getDynamicQueryParamThreadLocal() {
  83.         // До этого где-нибудь в сервисе заполняем ThreadLocal в DynamicQueryContextHolder
  84.         return DynamicQueryContextHolder.getDynamicQueryParam();
  85.     }
  86.  
  87.     // Наш холдер контекста запроса, можем использовать его в любых местах, если нужна динамика в параметре
  88.     static class DynamicQueryContextHolder {
  89.  
  90.         private static final ThreadLocal<String> DYNAMIC_QUERY_PARAM_CONTEXT_HOLDER = new ThreadLocal<>();
  91.  
  92.         public static void setDynamicQueryParam(String dynamicQueryParam) {
  93.             DYNAMIC_QUERY_PARAM_CONTEXT_HOLDER.set(dynamicQueryParam);
  94.         }
  95.  
  96.         public static String getDynamicQueryParam() {
  97.             return DYNAMIC_QUERY_PARAM_CONTEXT_HOLDER.get();
  98.         }
  99.  
  100.         public static void clear() {
  101.             DYNAMIC_QUERY_PARAM_CONTEXT_HOLDER.remove();
  102.         }
  103.  
  104.     }
  105.  
  106. }
  107.  
  108. package my.example.mybatis.model;
  109.  
  110. import lombok.Builder;
  111. import lombok.Getter;
  112.  
  113. @Builder
  114. @Getter
  115. public class SomeParams {
  116.  
  117.     private String value;
  118.  
  119. }
  120.  
Tags: MyBatis
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement