In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-22 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
This article mainly explains "what is the implementation of mybatis/mybatis-plus fuzzy query sentence special character escape interceptor", interested friends may wish to have a look. The method introduced in this paper is simple, fast and practical. Next let the editor to take you to learn "mybatis/mybatis-plus fuzzy query statement special character escape interceptor is what is the implementation of it?"
1. Use the interceptor provided by mybatis to intercept all query requests.
The specific implementation is commented in the code.
Import lombok.extern.slf4j.Slf4j;import org.apache.commons.lang3.StringUtils;import org.apache.ibatis.executor.Executor;import org.apache.ibatis.mapping.BoundSql;import org.apache.ibatis.mapping.MappedStatement;import org.apache.ibatis.plugin.*;import org.apache.ibatis.session.ResultHandler;import org.apache.ibatis.session.RowBounds;import java.util.* / * mybatis/mybatis-plus fuzzy query statement special character escape interceptor * * @ author lieber * / @ Intercepts ({@ Signature (type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}) @ Slf4jpublic class MybatisLikeSqlInterceptor implements Interceptor {/ * * SQL statement like * / private final static String SQL_LIKE = "like" / * * SQL statement placeholder * / private final static String SQL_PLACEHOLDER = "?"; / * SQL statement placeholder separation * / private final static String SQL_PLACEHOLDER_REGEX = "\\?"; / * all escapers * / private static Map converterMap = new HashMap (4); static {converterMap.put (Map.class, new MapLikeSqlConverter ()) ConverterMap.put (Object.class, new ObjectLikeSqlConverter ());} @ Override public Object intercept (Invocation invocation) throws Throwable {Object [] args = invocation.getArgs (); MappedStatement statement = (MappedStatement) args [0]; Object parameterObject = args [1]; BoundSql boundSql = statement.getBoundSql (parameterObject); String sql = boundSql.getSql (); this.transferLikeSql (sql, parameterObject, boundSql); return invocation.proceed () } @ Override public Object plugin (Object target) {return Plugin.wrap (target, this) } @ Override public void setProperties (Properties arg0) {} / * modify the SQL statement containing like * * @ param sql SQL statement * @ param parameterObject parameter object * @ param boundSql bind SQL object * / private void transferLikeSql (String sql, Object parameterObject BoundSql boundSql) {if (! isEscape (sql)) {return } sql = sql.replaceAll ("{2}", ""); / / get the number of keywords (deduplicated) Set fields = this.getKeyFields (sql, boundSql); if (fields = = null) {return } / / can be enhanced here, not only supporting Map objects, Map objects are only used for Map AbstractLikeSqlConverter converter where the condition passed in is Map or the object passed in using @ Param is converted by Mybatis / / A pair of keywords are cleaned with special characters. If there are special characters, the escape character (\) if (parameterObject instanceof Map) {converter = converterMap.get (Map.class) {converter = converterMap.get (Object.class);} converter.convert (sql, fields, parameterObject) is added before the special characters. } / * * do you need to escape the * * @ param sql SQL statement * @ return true/false * / private boolean isEscape (String sql) {return this.hasLike (sql) & & this.hasPlaceholder (sql) } / * determine whether the SQL statement contains the like keyword * * @ param str SQL statement * @ return true/false * / private boolean hasLike (String str) {if (StringUtils.isBlank (str)) {return false;} return str.toLowerCase (). Contains (SQL_LIKE) } / * determine whether the SQL statement contains the SQL placeholder * * @ param str SQL statement * @ return true/false * / private boolean hasPlaceholder (String str) {if (StringUtils.isBlank (str)) {return false;} return str.toLowerCase () .contains (SQL_PLACEHOLDER) } / * get the collection of all fields to be replaced * * @ param sql complete SQL statement * @ SQL object bound by param boundSql * @ return field collection list * / private Set getKeyFields (String sql, BoundSql boundSql) {String [] params = sql.split (SQL_PLACEHOLDER_REGEX); Set fields = new HashSet () For (int I = 0; I < params.length; iTunes +) {if (this.hasLike (params [I])) {String field = boundSql.getParameterMappings (). Get (I). GetProperty (); fields.add (field);}} return fields;} 2. Define an escape template for SQL statements to handle Map and Object objects respectively
2.1Definition AbstractLikeSqlConverter
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;/** * SQL statement escape template containing like * * @ author lieber * / @ Slf4jpublic abstract class AbstractLikeSqlConverter {/ * SQL statement like uses the keyword% * / private final static String LIKE_SQL_KEY = "%" / * keywords to be escaped by SQL statement * / private final static String [] ESCAPE_CHAR = new String [] {LIKE_SQL_KEY, "_", "\"}; / * * SQL statement style of like in mybatis-plus * / private final static String MYBATIS_PLUS_LIKE_SQL = "like?" Parameter prefix * / private final static String MYBATIS_PLUS_WRAPPER_PREFIX = "ew.paramNameValuePairs." in / * mybatis-plus; parameter key * / final static String MYBATIS_PLUS_WRAPPER_KEY = "ew" in / * mybatis-plus; parameter delimiter * / final static String MYBATIS_PLUS_WRAPPER_SEPARATOR = "." in / * mybatis-plus. " Parameter separator in / * mybatis-plus * / final static String MYBATIS_PLUS_WRAPPER_SEPARATOR_REGEX = "\\."; / * the tag that has been replaced * / final static String REPLACED_LIKE_KEYWORD_MARK = "replaced.keyword" / * escape special character * * @ param sql SQL statement * @ param fields field list * @ param parameter parameter object * / public void convert (String sql, Set fields T parameter) {for (String field: fields) {if (this.hasMybatisPlusLikeSql (sql)) {if (this.hasWrapper (field)) {/ / the first case: fuzzy query keywords generated by conditional construction at the business layer, using QueryWrapper,LambdaQueryWrapper this.transferWrapper (field, parameter) } else {/ / second case: conditional constructor is not used, but query keywords and fuzzy query character `%` are manually stitched in the service layer this.transferSelf (field, parameter) }} else {/ / third case: the this.transferSplice (field, parameter) of fuzzy query is concatenated in the note SQL of Mapper class. } / * escape the special character constructed by the condition * the fuzzy query keyword generated by conditional construction at the business layer, using the QueryWrapper,LambdaQueryWrapper * * @ param field field name * @ param parameter parameter object * / public abstract void transferWrapper (String field, T parameter) / * * escape special characters of custom conditional stitching * do not use conditional constructor, but query keywords and fuzzy query character `%` are manually concatenated at service layer * * @ param field field name * @ param parameter parameter object * / public abstract void transferSelf (String field, T parameter) / * * escape special characters of custom conditional stitching * concatenate fuzzy query * * @ param field field name * @ param parameter parameter object * / public abstract void transferSplice (String field, T parameter) in the note SQL of Mapper class / * escape wildcard * * @ param before string to be escaped * @ return string * / String escapeChar (String before) {if (StringUtils.isNotBlank (before)) {before = before.replaceAll ("\\", "\") Before = before.replaceAll ("_", "\"); before = before.replaceAll ("%", "\%");} return before } / * whether it contains the character to be escaped * * @ param obj object to be determined * @ return true/false * / boolean hasEscapeChar (Object obj) {if (! (obj instanceof String)) {return false;} return this.hasEscapeChar ((String) obj) } / * deal with like problem of object * * @ param field object Field * @ param parameter object * / 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 ("abnormal reflection of {} get/set method", parameter, field, e) }} / * determine whether the cascading attribute * * @ param field field name * @ return true/false * / boolean cascade (String field) {if (StringUtils.isBlank (field)) {return false;} return field.contains (MYBATIS_PLUS_WRAPPER_SEPARATOR) & &! this.hasWrapper (field) } / * whether to include mybatis-plus 's SQL statement format including like * * @ param sql complete SQL statement * @ return true/false * / private boolean hasMybatisPlusLikeSql (String sql) {if (StringUtils.isBlank (sql)) {return false;} return sql.toLowerCase () .contains (MYBATIS_PLUS_LIKE_SQL) } / * determine whether to use the mybatis-plus condition constructor * * @ param field field * @ return true/false * / private boolean hasWrapper (String field) {if (StringUtils.isBlank (field)) {return false;} return field.contains (MYBATIS_PLUS_WRAPPER_PREFIX) } / * determine whether the string contains the character to be escaped * * @ param str string to be judged * @ 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;}}
2.2 define how MapLikeSqlConverter handles Map type parameters
Import com.baomidou.mybatisplus.core.conditions.AbstractWrapper;import java.util.Map;import java.util.Objects;/** * Converter whose parameter object is Map * * @ author lieber * @ create_date 12:28 on 2020-1-21 * / public class MapLikeSqlConverter extends AbstractLikeSqlConverter {@ Override public void transferWrapper (String field, Map parameter) {AbstractWrapper wrapper = (AbstractWrapper) parameter.get (MYBATIS_PLUS_WRAPPER_KEY); parameter = wrapper.getParamNameValuePairs () String [] keys = field.split (MYBATIS_PLUS_WRAPPER_SEPARATOR_REGEX); / / ew.paramNameValuePairs.param1. After intercepting the string, get the third, that is, the parameter name String paramName = keys [2]; String mapKey = String.format ("% s% s", REPLACED_LIKE_KEYWORD_MARK, paramName) If (parameter.containsKey (mapKey) & & Objects.equals (parameter.get (mapKey), true)) {return;} if (this.cascade (field)) {this.resolveCascadeObj (field, parameter);} else {Object param = parameter.get (paramName); if (this.hasEscapeChar (param)) {String paramStr = param.toString () Parameter.put (keys [2], String.format ("%% s%%", this.escapeChar (paramStr.substring (1, paramStr.length ()-1);}} parameter.put (mapKey, true);} @ Override public void transferSelf (String field, Map parameter) {if (this.cascade (field)) {this.resolveCascadeObj (field, parameter) Return;} Object param = parameter.get (field); if (this.hasEscapeChar (param)) {String paramStr = param.toString (); parameter.put (field, String.format ("%% s%%", this.escapeChar (paramStr.substring (1, paramStr.length ()-1) } @ Override public void transferSplice (String field, Map parameter) {if (this.cascade (field)) {this.resolveCascadeObj (field, parameter); return;} Object param = parameter.get (field); if (this.hasEscapeChar (param)) {parameter.put (field, this.escapeChar (param.toString () }} / * handle cascading attribute * * @ param field cascading field name * @ param parameter parameter Map object * / private void resolveCascadeObj (String field, Map parameter) {int index = field.indexOf (MYBATIS_PLUS_WRAPPER_SEPARATOR); Object param = parameter.get (field.substring (0, index)) If (param = = null) {return;} this.resolveObj (field.substring (index + 1), param);}}
2.3Definitions of ObjectLikeSqlConverter handling of Object type parameters
Import lombok.extern.slf4j.Slf4j / * @ author lieber * / @ Slf4jpublic class ObjectLikeSqlConverter extends AbstractLikeSqlConverter {@ Override public void transferWrapper (String field, Object parameter) {/ / this situation has not been found} @ Override public void transferSelf (String field, Object parameter) {/ / not found yet} @ Override public void transferSplice (String field, Object parameter) {this.resolveObj (field, parameter) }}
3. Register with Spring
Import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;/** * mybatis/mybatis-plus Fuzzy query statement Special character escape configuration * * @ author lieber * / @ Configurationpublic class MybatisLikeSqlConfig {@ Bean public MybatisLikeSqlInterceptor mybatisSqlInterceptor () {return new MybatisLikeSqlInterceptor ();}}
At this point, the keyword can be matched exactly.
At this point, I believe that everyone on the "mybatis/mybatis-plus fuzzy query statement special character escape interceptor is what is the implementation of" have a deeper understanding, might as well to the actual operation of it! Here is the website, more related content can enter the relevant channels to inquire, follow us, continue to learn!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.