├── README.md ├── pom.xml ├── sqladder-1.0-SNAPSHOT.jar └── src └── main └── java └── cn └── localhost01 ├── ReflectUtil.java ├── SqlAdder.java └── SqlAdderException.java /README.md: -------------------------------------------------------------------------------- 1 | # 插件介绍 2 | Mybatis条件动态添加插件,用于书写少量代码(一句话代码,类似`pagehelper的PageHelper.startPage(currentPage, branchSize)`),以完成一些查询条件的添加。 3 | 4 | # 使用场景 5 | 你有一个查询所有学生的接口。这时有个需求是查询“有效”的学生,或是查询年龄为18岁以上的学生,又或是查询所有男生等等,这时,你要么将接口重构或重载,动态传入sql,或者分别为不同需求,在dao中书写不同接口。前者每次需要写不同sql,后者就不知道要写多少个接口。因此你可以使用Mybatis-SqlAdder,为查询语句动态添加条件,如下: 6 | 7 | * `SqlAdder.addSqlCond("s_enable=0");` `studentMapper.selectAllList();` 8 | 9 | * `SqlAdder.addSqlCond("s_age>18");` `studentMapper.selectAllList();` 10 | 11 | * `SqlAdder.addSqlCond("s_gender=1");` `studentMapper.selectAllList();` 12 | 13 | # 使用说明 14 | 1. 在mybatis配置文件中,添加类似如下: 15 | ```xml 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | ``` 33 | 34 | 2. 代码使用示例: 35 | `SqlAdder.add("where car_enable=1");` 36 | `studentMapper.selectAllList();` 37 | 38 | # 依赖 39 | ```xml 40 | 41 | org.mybatis 42 | mybatis 43 | 3.2.6 44 | compile 45 | true 46 | 47 | 48 | org.slf4j 49 | slf4j-api 50 | 1.7.25 51 | 52 | ``` 53 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | cn.localhost01 8 | sqladder 9 | 1.0-SNAPSHOT 10 | jar 11 | 12 | sqladder 13 | Mybatis SqlAdd Plugin 14 | https://github.com/localhost02/Mybatis-sqladder 15 | 16 | 17 | UTF-8 18 | 19 | 20 | 21 | 22 | org.mybatis 23 | mybatis 24 | 3.2.6 25 | compile 26 | true 27 | 28 | 29 | org.slf4j 30 | slf4j-api 31 | 1.7.25 32 | 33 | 34 | junit 35 | junit 36 | 3.8.1 37 | test 38 | 39 | 40 | 41 | 42 | 43 | 44 | src/test/resources 45 | 46 | 47 | src/test/java 48 | 49 | 50 | 51 | 52 | 53 | 54 | release 55 | 56 | 57 | 58 | 59 | maven-compiler-plugin 60 | 61 | 1.6 62 | 1.6 63 | 64 | 65 | 66 | 67 | org.apache.maven.plugins 68 | maven-source-plugin 69 | 2.2.1 70 | 71 | 72 | package 73 | 74 | jar-no-fork 75 | 76 | 77 | 78 | 79 | 80 | 81 | org.apache.maven.plugins 82 | maven-javadoc-plugin 83 | 2.9.1 84 | 85 | 86 | package 87 | 88 | jar 89 | 90 | 91 | 92 | 93 | 94 | 95 | org.apache.maven.plugins 96 | maven-gpg-plugin 97 | 98 | 99 | sign-artifacts 100 | verify 101 | 102 | sign 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | oss 112 | https://oss.sonatype.org/content/repositories/snapshots/ 113 | 114 | 115 | oss 116 | https://oss.sonatype.org/service/local/staging/deploy/maven2/ 117 | 118 | 119 | 120 | 121 | 122 | 123 | -------------------------------------------------------------------------------- /sqladder-1.0-SNAPSHOT.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/localhost02/Mybatis-SqlAdder/c1d08b6d19c5c4d7427ff00ccc7d06983fa21c68/sqladder-1.0-SNAPSHOT.jar -------------------------------------------------------------------------------- /src/main/java/cn/localhost01/ReflectUtil.java: -------------------------------------------------------------------------------- 1 | package cn.localhost01; 2 | 3 | import java.lang.reflect.Field; 4 | import java.lang.reflect.Method; 5 | import java.lang.reflect.Modifier; 6 | 7 | public abstract class ReflectUtil { 8 | 9 | public static void setFieldValue(Object target, String fname, Object fvalue) throws SqlAdderException { 10 | // 如果类型不匹配,直接退出 11 | if (target == null || fname == null || "".equals(fname)) 12 | return; 13 | 14 | Class clazz = target.getClass(); 15 | 16 | try { // 通过set方法设置类属性值 17 | String methodname = "set" + Character.toUpperCase(fname.charAt(0)) + fname.substring(1); 18 | Method method = clazz.getDeclaredMethod(methodname, fvalue.getClass()); // 获取定义的方法 19 | 20 | if (!Modifier.isPublic(method.getModifiers())) // 设置非共有方法权限 21 | method.setAccessible(true); 22 | 23 | // 执行方法回调 24 | method.invoke(target, fvalue); 25 | } catch (Exception e) {// 如果set方法不存在,则直接设置类属性值 26 | try { 27 | Field field = clazz.getDeclaredField(fname); // 获取定义的类属性 28 | 29 | if (!Modifier.isPublic(field.getModifiers())) // 设置非共有类属性权限 30 | field.setAccessible(true); 31 | 32 | field.set(target, fvalue); // 设置类属性值 33 | } catch (Exception ex) { 34 | throw new SqlAdderException("设置属性值时错误", ex); 35 | } 36 | 37 | } 38 | } 39 | 40 | public static Object getFieldValue(Object target, String fname) throws SqlAdderException { 41 | 42 | if (target == null || fname == null || "".equals(fname)) 43 | return null; 44 | 45 | Class clazz = target.getClass(); 46 | 47 | try { // 通过get方法获取类属性值 48 | String methodname = "get" + Character.toUpperCase(fname.charAt(0)) + fname.substring(1); 49 | Method method = clazz.getDeclaredMethod(methodname); // 获取定义的方法 50 | 51 | if (!Modifier.isPublic(method.getModifiers())) // 设置非共有方法权限 52 | method.setAccessible(true); 53 | 54 | return method.invoke(target); // 方法回调,返回值 55 | } catch (Exception e) {// 如果get方法不存在,则直接获取类属性值 56 | try { 57 | Field field = clazz.getDeclaredField(fname); // 获取定义的类属性 58 | 59 | if (!Modifier.isPublic(field.getModifiers())) // 设置非共有类属性权限 60 | field.setAccessible(true); 61 | 62 | return field.get(target);// 返回类属性值 63 | } catch (Exception ex) { 64 | throw new SqlAdderException("获取属性值时错误", ex); 65 | } 66 | 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/cn/localhost01/SqlAdder.java: -------------------------------------------------------------------------------- 1 | package cn.localhost01; 2 | 3 | import org.apache.ibatis.executor.statement.StatementHandler; 4 | import org.apache.ibatis.mapping.BoundSql; 5 | import org.apache.ibatis.plugin.*; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | import java.sql.Connection; 10 | import java.util.Properties; 11 | import java.util.regex.Pattern; 12 | 13 | /** 14 | * 描述:Mybatis SQL条件添加器
15 | * 一般适用于sql中只有一个where语句的SQL,如果SQL较复杂,如有多个where以及嵌套子查询等,请避免使用本工具类。另外会和pagehelper启用总数查询时冲突! 16 | * 17 | * @author 冉椿林 18 | * @date 2017年7月22日 下午3:37:55 19 | */ 20 | @Intercepts(@Signature(type = StatementHandler.class, method = "prepare", args = { 21 | Connection.class })) public class SqlAdder implements Interceptor { 22 | 23 | private String sql_Intercept; 24 | private String sql_Not_Intercept; 25 | private boolean is_print_sql = false; 26 | 27 | private static final ThreadLocal LOCAL_CONDITION = new ThreadLocal(); 28 | private static final Logger logger = LoggerFactory.getLogger(SqlAdder.class); 29 | 30 | /** 31 | * Description:开始进行SQL拦截
32 | * 33 | * @param sqlCondition 要添加的条件语句 34 | * 35 | * @author ran.chunlin 36 | * @date 2017年7月24日 下午5:38:19 37 | * @version 1.0 38 | */ 39 | public static void addSqlCond(String sqlCondition) { 40 | LOCAL_CONDITION.set(sqlCondition); 41 | } 42 | 43 | public Object intercept(Invocation inv) throws Throwable { 44 | String condition = LOCAL_CONDITION.get(); 45 | 46 | LOCAL_CONDITION.remove(); 47 | 48 | StatementHandler target = (StatementHandler) inv.getTarget(); 49 | BoundSql boundSql = target.getBoundSql(); 50 | String sql = boundSql.getSql().toLowerCase(); 51 | 52 | if (condition == null) 53 | return inv.proceed(); 54 | 55 | // 只有select语句才进行下一步 56 | if (Pattern.matches(sql_Intercept, sql) && ("".equals(sql_Not_Intercept) ? 57 | true : 58 | !Pattern.matches(sql_Not_Intercept, sql))) { 59 | String newSql = null; 60 | String lowerSql = sql.toLowerCase(); 61 | 62 | if (lowerSql.matches("[\\s\\S]+\\s+where\\s+[\\s\\S]+$")) 63 | newSql = lowerSql.replaceAll("\\swhere\\s", " " + condition + " and "); 64 | else if (lowerSql.matches("[\\s\\S]+\\s+gourp\\s+by\\s+[\\s\\S]+$")) 65 | newSql = lowerSql.replaceAll("\\sgourp\\s+by\\s", " " + condition + " gourp by "); 66 | else if (lowerSql.matches("[\\s\\S]+\\s+order\\s+by\\s+[\\s\\S]+$")) 67 | newSql = lowerSql.replaceAll("\\sorder\\s+by\\s", " " + condition + " order by "); 68 | else if (lowerSql.matches("[\\s\\S]+\\s+limit\\s+[\\s\\S]+$")) 69 | newSql = lowerSql.replaceAll("\\slimit\\s", " " + condition + " limit "); 70 | else 71 | newSql = lowerSql + " " + condition; 72 | 73 | if (newSql != null) { 74 | ReflectUtil.setFieldValue(boundSql, "sql", newSql); 75 | 76 | if (is_print_sql) 77 | logger.info("......\n====================================print sql====================================\nraw sql:" + boundSql.getSql() + "\nparams:" 78 | + boundSql.getParameterObject() + "\nnew sql:" + newSql 79 | + "\n====================================print sql===================================="); 80 | } 81 | } 82 | return inv.proceed(); 83 | } 84 | 85 | public Object plugin(Object target) { 86 | return Plugin.wrap(target, this); 87 | } 88 | 89 | public void setProperties(Properties arg0) { 90 | } 91 | 92 | public void setSql_Intercept(String sql_Intercept) { 93 | this.sql_Intercept = sql_Intercept; 94 | } 95 | 96 | public void setSql_Not_Intercept(String sql_Not_Intercept) { 97 | this.sql_Not_Intercept = sql_Not_Intercept; 98 | } 99 | 100 | public void setIs_print_sql(boolean is_print_sql) { 101 | this.is_print_sql = is_print_sql; 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/main/java/cn/localhost01/SqlAdderException.java: -------------------------------------------------------------------------------- 1 | package cn.localhost01; 2 | 3 | public class SqlAdderException extends Exception { 4 | public SqlAdderException() { 5 | super(); 6 | } 7 | 8 | public SqlAdderException(String message) { 9 | super(message); 10 | } 11 | 12 | public SqlAdderException(String message, Throwable cause) { 13 | super(message, cause); 14 | } 15 | 16 | public SqlAdderException(Throwable cause) { 17 | super(cause); 18 | } 19 | } 20 | --------------------------------------------------------------------------------