123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223 |
- package com.lantone.dblayermbg.config.mybatisLike;
- import lombok.extern.slf4j.Slf4j;
- import org.apache.commons.lang3.StringUtils;
- import java.beans.IntrospectionException;
- import java.beans.PropertyDescriptor;
- import java.lang.reflect.InvocationTargetException;
- import java.lang.reflect.Method;
- import java.util.Set;
- /**
- * @Description: 包含like的SQL语句转义模板
- * @author: gaodm
- * @time: 2020/11/2 16:05
- */
- @Slf4j
- public abstract class AbstractLikeSqlConverter<T> {
- /**
- * SQL语句like使用关键字%
- */
- private final static String LIKE_SQL_KEY = "%";
- /**
- * SQL语句需要转义的关键字
- */
- private final static String[] ESCAPE_CHAR = new String[] { LIKE_SQL_KEY, "_", "\\" };
- /**
- * mybatis-plus中like的SQL语句样式
- */
- private final static String MYBATIS_PLUS_LIKE_SQL = " like ?";
- /**
- * mybatis-plus中参数前缀
- */
- private final static String MYBATIS_PLUS_WRAPPER_PREFIX = "ew.paramNameValuePairs.";
- /**
- * mybatis-plus中参数键
- */
- final static String MYBATIS_PLUS_WRAPPER_KEY = "ew";
- /**
- * mybatis-plus中参数分隔符
- */
- final static String MYBATIS_PLUS_WRAPPER_SEPARATOR = ".";
- /**
- * mybatis-plus中参数分隔符替换器
- */
- final static String MYBATIS_PLUS_WRAPPER_SEPARATOR_REGEX = "\\.";
- /**
- * 已经替换过的标记
- */
- final static String REPLACED_LIKE_KEYWORD_MARK = "replaced.keyword";
- /**
- * 转义特殊字符
- *
- * @param sql SQL语句
- * @param fields 字段列表
- * @param parameter 参数对象
- */
- public void convert(String sql, Set<String> fields, T parameter) {
- for (String field : fields) {
- if (this.hasMybatisPlusLikeSql(sql)) {
- if (this.hasWrapper(field)) {
- // 第一种情况:在业务层进行条件构造产生的模糊查询关键字,使用QueryWrapper,LambdaQueryWrapper
- this.transferWrapper(field, parameter);
- } else {
- // 第二种情况:未使用条件构造器,但是在service层进行了查询关键字与模糊查询符`%`手动拼接
- this.transferSelf(field, parameter);
- }
- } else {
- // 第三种情况:在Mapper类的注解SQL中进行了模糊查询的拼接
- this.transferSplice(field, parameter);
- }
- }
- }
- /**
- * 转义条件构造的特殊字符
- * 在业务层进行条件构造产生的模糊查询关键字,使用QueryWrapper,LambdaQueryWrapper
- *
- * @param field 字段名称
- * @param parameter 参数对象
- */
- public abstract void transferWrapper(String field, T parameter);
- /**
- * 转义自定义条件拼接的特殊字符
- * 未使用条件构造器,但是在service层进行了查询关键字与模糊查询符`%`手动拼接
- *
- * @param field 字段名称
- * @param parameter 参数对象
- */
- public abstract void transferSelf(String field, T parameter);
- /**
- * 转义自定义条件拼接的特殊字符
- * 在Mapper类的注解SQL中进行了模糊查询的拼接
- *
- * @param field 字段名称
- * @param parameter 参数对象
- */
- public abstract void transferSplice(String field, T parameter);
- /**
- * 转义通配符
- *
- * @param before 待转义字符串
- * @return 转义后字符串
- */
- String escapeChar(String before) {
- if (StringUtils.isNotBlank(before)) {
- before = before.replaceAll("\\\\", "\\\\\\\\");
- before = before.replaceAll("_", "\\\\_");
- before = before.replaceAll("%", "\\\\%");
- }
- return before;
- }
- /**
- * 是否包含需要转义的字符
- *
- * @param obj 待判断的对象
- * @return true/false
- */
- boolean hasEscapeChar(Object obj) {
- if (!(obj instanceof String)) {
- return false;
- }
- return this.hasEscapeChar((String) obj);
- }
- /**
- * 处理对象like问题
- *
- * @param field 对象字段
- * @param parameter 对象
- */
- void resolveObj(String field, Object parameter) {
- if (parameter == null || StringUtils.isBlank(field)) {
- return;
- }
- try {
- PropertyDescriptor descriptor = new PropertyDescriptor(field, parameter.getClass());
- Method readMethod = descriptor.getReadMethod();
- Object param = readMethod.invoke(parameter);
- if (this.hasEscapeChar(param)) {
- Method setMethod = descriptor.getWriteMethod();
- setMethod.invoke(parameter, this.escapeChar(param.toString()));
- } else if (this.cascade(field)) {
- int index = field.indexOf(MYBATIS_PLUS_WRAPPER_SEPARATOR) + 1;
- this.resolveObj(field.substring(index), param);
- }
- } catch (IntrospectionException | IllegalAccessException | InvocationTargetException e) {
- log.error("反射 {} 的 {} get/set方法出现异常", parameter, field, e);
- }
- }
- /**
- * 判断是否是级联属性
- *
- * @param field 字段名
- * @return true/false
- */
- boolean cascade(String field) {
- if (StringUtils.isBlank(field)) {
- return false;
- }
- return field.contains(MYBATIS_PLUS_WRAPPER_SEPARATOR) && !this.hasWrapper(field);
- }
- /**
- * 是否包含mybatis-plus的包含like的SQL语句格式
- *
- * @param sql 完整SQL语句
- * @return true/false
- */
- private boolean hasMybatisPlusLikeSql(String sql) {
- if (StringUtils.isBlank(sql)) {
- return false;
- }
- return sql.toLowerCase().contains(MYBATIS_PLUS_LIKE_SQL);
- }
- /**
- * 判断是否使用mybatis-plus条件构造器
- *
- * @param field 字段
- * @return true/false
- */
- private boolean hasWrapper(String field) {
- if (StringUtils.isBlank(field)) {
- return false;
- }
- return field.contains(MYBATIS_PLUS_WRAPPER_PREFIX);
- }
- /**
- * 判断字符串是否含有需要转义的字符
- *
- * @param str 待判断的字符串
- * @return true/false
- */
- private boolean hasEscapeChar(String str) {
- if (StringUtils.isBlank(str)) {
- return false;
- }
- for (String s : ESCAPE_CHAR) {
- if (str.contains(s)) {
- return true;
- }
- }
- return false;
- }
- }
|