├── 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 |
--------------------------------------------------------------------------------