Java 如何在mybatis中动态拦截和更改sql查询
我使用mybatis在项目中执行sql查询。我需要在执行之前截取sql查询以动态应用一些更改。我读过关于@interoptor的文章,比如:Java 如何在mybatis中动态拦截和更改sql查询,java,sql,mybatis,Java,Sql,Mybatis,我使用mybatis在项目中执行sql查询。我需要在执行之前截取sql查询以动态应用一些更改。我读过关于@interoptor的文章,比如: @Intercepts({@Signature(type= Executor.class, method = "query", args = {...})}) public class ExamplePlugin implements Interceptor { public Object intercept(Invocation invocation
@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查询吗?拦截查询执行以动态更改查询执行的正确位置在哪里?谢谢。 你可以考虑使用一个字符串模板库(如速度、把手、胡子)来帮助你
到目前为止,甚至还有MyBatis Velocity()可以帮助您为sql编写脚本。根据您想要进行的更改,您可能需要使用MyBatis 3的功能。我希望它能帮助您:
@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)
{
}
}
@拦截({@Signature(type=Executor.class,method=“query”,args={
MappedStatement.class、Object.class、RowBounds.class、,
ResultHandler.class
})
})
公共类SelectCountSqlInterceptor 2实现拦截器
{
公共静态字符串计数=“\u计数”;
私有静态int映射_语句_索引=0;
私有静态int参数_INDEX=1;
@凌驾
公共对象拦截(调用)抛出可丢弃的
{
processCountSql(invocation.getArgs());
返回调用。继续();
}
@抑制警告(“原始类型”)
私有void processCountSql(最终对象[]queryArgs)
{
if(queryArgs[参数索引]映射实例)
{
Map参数=(Map)queryArgs[参数_索引];
if(参数containsKey(计数))
{
MappedStatement ms=(MappedStatement)queryArgs[映射的语句索引];
BoundSql BoundSql=ms.getBoundSql(参数);
字符串sql=ms.getBoundSql(参数).getSql().trim();
BoundSql newBoundSql=新的BoundSql(ms.getConfiguration(),
getCountSQL(sql),boundSql.getParameterMappings(),
boundSql.getParameterObject());
MappedStatement newMs=copyFromMappedStatement(ms,
新的offsetlimitterceptor.boundsqlsource(newBoundSql));
queryArgs[MAPPED_STATEMENT_INDEX]=newMs;
}
}
}
//请参阅:MapperBuilderAsistant
@SuppressWarnings({“unchecked”,“rawtypes”})
私有MappedStatement copyFromMappedStatement(MappedStatement ms,
SqlSource新闻(SqlSource)
{
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()
超时(ms.getTimeout());
//setParameterMap()
builder.parameterMap(ms.getParameterMap());
//setStatementResultMap()
List resultmap=new ArrayList();
字符串id=“-inline”;
如果(ms.getResultMaps()!=null)
{
id=ms.getResultMaps().get(0.getId()+“-inline”;
}
ResultMap ResultMap=new ResultMap.Builder(null,id,Long.class,
新建ArrayList()).build();
结果映射。添加(结果映射);
builder.resultmap(resultmap);
builder.resultsetype(ms.getresultsetype());
//setStatementCache()
builder.cache(ms.getCache());
builder.flushCacheRequired(ms.isFlushCacheRequired());
builder.useCache(ms.isUseCache());
返回builder.build();
}
私有字符串getCountSQL(字符串sql)
{
String lowerCaseSQL=sql.toLowerCase().replace(“\n”,”).replace(“\t”,”);
int index=小写的ql.indexOf(“顺序”);
如果(索引!=-1)
{
sql=sql.substring(0,索引);
}
返回“SELECT COUNT(*)from(选择1作为列c)+sql.substring(小写sql.indexOf(“from”)+”)cnt”;
}
@凌驾
公共对象插件(对象目标)
{
返回Plugin.wrap(target,this);
}
@凌驾
公共void集合属性(属性)
{
}
}
您有这样的例子吗?我觉得这份文件没有多大用处