MyBatis Like查询处理%_符号
如果我们数据库中存的字段包含有"%_"这两个like查询的通配符,那么在查询的时候把"%_"当作关键字是查询不出来的,因为mybatis会把这两个字符当作通配符。解决方法是要能加转义字符
1.定义一个拦截器,如果要查询的字符串中包含"%_"则增加一个转义字符
@Intercepts({
@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class,
RowBounds.class, ResultHandler.class})})
public class QueryExecutorInterceptor implements Interceptor { private static final ObjectFactory DEFAULT_OBJECT_FACTORY = new DefaultObjectFactory();
private static final ObjectWrapperFactory DEFAULT_OBJECT_WRAPPER_FACTORY = new DefaultObjectWrapperFactory();
private static final ReflectorFactory DEFAULT_OBJECT_REFLECTOR_FACTORY = new DefaultReflectorFactory();
private static final String ROOT_SQL_NODE = "sqlSource.rootSqlNode"; @Override
public Object intercept(Invocation invocation) throws Throwable {
Object parameter = invocation.getArgs()[1];
MappedStatement statement = (MappedStatement) invocation.getArgs()[0];
MetaObject metaMappedStatement = MetaObject.forObject(statement, DEFAULT_OBJECT_FACTORY, DEFAULT_OBJECT_WRAPPER_FACTORY, DEFAULT_OBJECT_REFLECTOR_FACTORY);
BoundSql boundSql = statement.getBoundSql(parameter);
if (metaMappedStatement.hasGetter(ROOT_SQL_NODE)) {
//修改参数值
SqlNode sqlNode = (SqlNode) metaMappedStatement.getValue(ROOT_SQL_NODE);
getBoundSql(statement.getConfiguration(), boundSql.getParameterObject(), sqlNode);
}
return invocation.proceed();
} @Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
} @Override
public void setProperties(Properties properties) {
} public static BoundSql getBoundSql(Configuration configuration, Object parameterObject, SqlNode sqlNode) {
DynamicContext context = new DynamicContext(configuration, parameterObject);
sqlNode.apply(context);
String countextSql = context.getSql();
SqlSourceBuilder sqlSourceParser = new SqlSourceBuilder(configuration);
Class<?> parameterType = parameterObject == null ? Object.class : parameterObject.getClass();
String sql = modifyLikeSql(countextSql, parameterObject);
SqlSource sqlSource = sqlSourceParser.parse(sql, parameterType, context.getBindings()); BoundSql boundSql = sqlSource.getBoundSql(parameterObject);
for (Map.Entry<String, Object> entry : context.getBindings().entrySet()) {
boundSql.setAdditionalParameter(entry.getKey(), entry.getValue());
}
return boundSql;
} public static String modifyLikeSql(String sql, Object parameterObject) {
if (parameterObject instanceof Map) {
} else {
return sql;
}
if (!sql.toLowerCase().contains("like"))
return sql;
String reg = "\\bLIKE\\b.*\\#\\{\\b.*\\}";
Pattern pattern = Pattern.compile(reg, Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(sql); List<String> replaceFiled = new ArrayList<String>(); while (matcher.find()) {
int n = matcher.groupCount();
for (int i = 0; i <= n; i++) {
String output = matcher.group(i);
if (output != null) {
String key = getParameterKey(output);
if (replaceFiled.indexOf(key) < 0) {
replaceFiled.add(key);
}
}
}
}
//修改参数
Map<String, Object> paramMab = (Map) parameterObject;
for (String key : replaceFiled) {
Object val = paramMab.get(key);
if (val != null && val instanceof String && (val.toString().contains("%") || val.toString().contains("_"))) {
val = val.toString().replaceAll("%", "/%").replaceAll("_", "/_");
paramMab.replace(key.toString(), val);
} }
return sql;
} private static String getParameterKey(String input) {
String key = "";
String[] temp = input.split("#");
if (temp.length > 1) {
key = temp[1];
key = key.replace("{", "").replace("}", "").split(",")[0];
}
return key.trim();
}
2. 对面的查询mapper like后面要加escape '/'
<select id="getList" resultMap="MultiResultMap" parameterType="java.util.Map">
SELECT * FROM SYS_TEST T
WHERE 1=1
<if test="_parameter.containsKey('key')">
AND UPPER(CONCAT(T.ROLE_NAME,T.ROLE_INFO)) LIKE UPPER (CONCAT(CONCAT('%', #{key, jdbcType=VARCHAR}),'%')) ESCAPE '/'
</if>
</select>
最好的做法是可以直接拦截SQL,然后在SQL后面自动加上ESCAPE '/',但还没有找到合适的方法
MyBatis Like查询处理%_符号的更多相关文章
- mybatis转义反斜杠_MyBatis Plus like模糊查询特殊字符_、\、%
在MyBatis Plus中,使用like查询特殊字符_,\,%时会出现以下情况: 1.查询下划线_,sql语句会变为"%_%",会导致返回所有结果.在MySQL中下划线" ...
- MyBatis关联查询 (association) 时遇到的某些问题/mybatis映射
先说下问题产生的背景: 最近在做一个用到MyBatis的项目,其中有个业务涉及到关联查询,我是将两个查询分开来写的,即嵌套查询,个人感觉这样更方便重用: 关联的查询使用到了动态sql,在执行查询时就出 ...
- MyBatis的查询
MyBatis的查询 在上一个MyBatis的核心API中介绍了SqlSessionFactoryBuilder.SqlSessionFactory以及SqlSession是什么,它们都有什么作用,本 ...
- MyBatis关联查询和懒加载错误
MyBatis关联查询和懒加载错误 今天在写项目时遇到了个BUG.先说一下背景,前端请求更新生产订单状态,后端从前端接收到生产订单ID进行查询,然后就有问题了. 先看控制台报错: org.apache ...
- Mybatis关联查询和数据库不一致问题分析与解决
Mybatis关联查询和数据库不一致问题分析与解决 本文的前提是,确定sql语句没有问题,确定在数据库中使用sql和项目中结果不一致. 在使用SpringMVC+Mybatis做多表关联时候,发现也不 ...
- myBatis批量查询操作,xml中使用foreach案例
使用场景:有一个订单表,实体类为OrderBase.java,订单有个状态为status值可能为"1,2,3,4,5,6",现在需要查询状态为"2,3,4"的订 ...
- MyBatis基础:MyBatis关联查询(4)
1. MyBatis关联查询简介 MyBatis中级联分为3中:association.collection及discriminator. ◊ association:一对一关联 ◊ collecti ...
- MyBatis关联查询,一对多关联查询
实体关系图,一个国家对应多个城市 一对多关联查询可用三种方式实现: 单步查询,利用collection标签为级联属性赋值: 分步查询: 利用association标签进行分步查询: 利用collect ...
- Ibatis/Mybatis模糊查询
Ibatis/Mybatis模糊查询 根据网络内容整理 Ibatis中 使用$代替#.此种方法就是去掉了类型检查,使用字符串连接,不过可能会有sql注入风险. Sql代码 select * from ...
随机推荐
- PL/SQL数据库,Oracle登录
用户名:TESTZYPX_9999 数据库:10.75.142.242:1521/orcl
- 关于闭包(closure)的一些概念
和其他大多数现代编程语言一样,JS也采用词法作用域,也就是说,函数的执行依赖于变量作用域,这个作用域是在函数定义时决定的,而不是函数调用时决定的.为了实现这种词法作用域,JS函数对象的内部状态不仅包含 ...
- css随笔1
1.简单清除浏览器样式 *{ padding: 0px; margin: 0px; } 2.得到屏幕范围的div html,body{ width: 1 ...
- 美国在研新药_读取单个PDF
QQ:231469242 读取下载美国在研新药PDF内数据:unii,分子式,分子重量,药品名,who,编码,.... PDF无逻辑规则,不能百分之百提取,只能部分提取 几个默认字段为空 # -*- ...
- Java多线程 2 线程的生命周期和状态控制
一.线程的生命周期 线程状态转换图: 1.新建状态 用new关键字和Thread类或其子类建立一个线程对象后,该线程对象就处于新生状态.处于新生状态的线程有自己的内存空间,通过调用start方法进入就 ...
- java enum
小谈Java Enum的多态性 博客分类: Java JavaAppleJDKJVMIDEA Enum+多态,我没说错,不过Enum是不可以被继承的,也不可以继承自别人,只是能实现接口而已,何谈多态 ...
- SQL记录
create table test( 教师号 integer , 星期一 integer null, 星期二 integer null, 星期三 integer null); insert into ...
- html5中画布和SVG的比较
SVG是基于XML的图形语言,在DOM解析中其每个元素都是可以用的,这样就可以为SCG元素附加JavaScript事件处理器,实现更加丰富的效果. 在SVG中,每个被绘制的图形均被视为对象,如果SVG ...
- 【转载学习前辈的经验】-- Mistakes I made (as a developer) 我(作为一名开发者)所犯过的错误
我 2006 年开始工作,至今已经 10 年.10 年是个里程碑,我开始回顾自己曾经犯过的错误,以及我希望从同行那里得到什么类型的忠告.一切都在快速改变,10 年了,我不能确定这些秘诀是否还有用. 不 ...
- Excel——使用OFFSET、MATCH、COUNTA实现二级菜单
如图所示,接下来提供两种办法实现: 1.将A.B.C.D定义为名称NAME. 2.设置一级菜单单元格数据有效性为NAME. 3.设置二级菜单格数据有效为: =OFFSET($A$1,MATCH($A6 ...