簡體   English   中英

如何在mybatis中動態攔截和更改sql查詢

[英]How to intercept and change sql query dynamically in mybatis

我使用mybatis在我的項目中執行sql查詢。 我需要在執行之前攔截sql查詢以動態應用一些更改。 我讀過這樣的@Interseptors:

@Intercepts({@Signature(type= Executor.class, method = "query", args = {...})})
public class ExamplePlugin implements Interceptor {
  public Object intercept(Invocation invocation) throws Throwable {
    return invocation.proceed();
  }
  public Object plugin(Object target) {
    return Plugin.wrap(target, this);
  }
  public void setProperties(Properties properties) {
  }
}

它確實攔截了執行,但由於適當的字段不可寫,因此無法更改sql查詢。 我應該手動構建整個對象的新實例來替換sql查詢嗎? 攔截查詢執行以動態更改它的正確位置在哪里? 謝謝。

我希望它會對你有所幫助:

@Intercepts( { @Signature(type = Executor.class, method = "query", args = {
        MappedStatement.class, Object.class, RowBounds.class,
        ResultHandler.class
    })
})
public class SelectCountSqlInterceptor2 implements Interceptor
{
    public static String COUNT = "_count";
    private static int MAPPED_STATEMENT_INDEX = 0;
    private static int PARAMETER_INDEX = 1;
    @Override
    public Object intercept(Invocation invocation) throws Throwable
    {
        processCountSql(invocation.getArgs());
        return invocation.proceed();
    }
    @SuppressWarnings("rawtypes")
    private void processCountSql(final Object[] queryArgs)
    {
        if (queryArgs[PARAMETER_INDEX] instanceof Map)
        {
            Map parameter = (Map) queryArgs[PARAMETER_INDEX];
            if (parameter.containsKey(COUNT))
            {
                MappedStatement ms = (MappedStatement) queryArgs[MAPPED_STATEMENT_INDEX];
                BoundSql boundSql = ms.getBoundSql(parameter);
                String sql = ms.getBoundSql(parameter).getSql().trim();
                BoundSql newBoundSql = new BoundSql(ms.getConfiguration(),
                                                    getCountSQL(sql), boundSql.getParameterMappings(),
                                                    boundSql.getParameterObject());
                MappedStatement newMs = copyFromMappedStatement(ms,
                                        new OffsetLimitInterceptor.BoundSqlSqlSource(newBoundSql));
                queryArgs[MAPPED_STATEMENT_INDEX] = newMs;
            }
        }
    }
    // see: MapperBuilderAssistant
    @SuppressWarnings({ "unchecked", "rawtypes" })
    private MappedStatement copyFromMappedStatement(MappedStatement ms,
            SqlSource newSqlSource)
    {
        Builder builder = new MappedStatement.Builder(ms.getConfiguration(), ms
                .getId(), newSqlSource, ms.getSqlCommandType());
        builder.resource(ms.getResource());
        builder.fetchSize(ms.getFetchSize());
        builder.statementType(ms.getStatementType());
        builder.keyGenerator(ms.getKeyGenerator());
        // setStatementTimeout()
        builder.timeout(ms.getTimeout());
        // setParameterMap()
        builder.parameterMap(ms.getParameterMap());
        // setStatementResultMap()
        List<ResultMap> resultMaps = new ArrayList<ResultMap>();
        String id = "-inline";
        if (ms.getResultMaps() != null)
        {
            id = ms.getResultMaps().get(0).getId() + "-inline";
        }
        ResultMap resultMap = new ResultMap.Builder(null, id, Long.class,
                new ArrayList()).build();
        resultMaps.add(resultMap);
        builder.resultMaps(resultMaps);
        builder.resultSetType(ms.getResultSetType());
        // setStatementCache()
        builder.cache(ms.getCache());
        builder.flushCacheRequired(ms.isFlushCacheRequired());
        builder.useCache(ms.isUseCache());
        return builder.build();
    }
    private String getCountSQL(String sql)
    {
        String lowerCaseSQL = sql.toLowerCase().replace("\n", " ").replace("\t", " ");
        int index = lowerCaseSQL.indexOf(" order ");
        if (index != -1)
        {
            sql = sql.substring(0, index);
        }
        return "SELECT COUNT(*) from ( select 1 as col_c " + sql.substring(lowerCaseSQL.indexOf(" from "))  + " )   cnt";
    }
    @Override
    public Object plugin(Object target)
    {
        return Plugin.wrap(target, this);
    }
    @Override
    public void setProperties(Properties properties)
    {
    }
}

您可以考慮使用字符串模板庫(例如Velocity,Handlebars,Moustache)來幫助您

截至目前,甚至還有MyBatis-Velocity( http://mybatis.github.io/velocity-scripting/ )來幫助您為sql編寫腳本。

根據您要進行的更改,您可能希望使用mybatis 3的動態sql功能

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM