第一步:定义sql 连接符枚举和sql 条件枚举
package com.miaomiao.common.enums;
/**
* @program: miaomiao
* @description:
* @author: lzy
* @create: 2020-11-03 09:56
*/
public enum SqlConnectEnum {
/**
* sql 链接属性 and
*/
AND,
/**
* sql 链接属性 or
*/
OR;
SqlConnectEnum() {
}
public static SqlConnectEnum fromString(String value) {
return valueOf(value.toLowerCase());
}
}
package com.miaomiao.common.enums;
/**
* @program: miaomiao
* @description:
* @author: lzy
* @create: 2020-10-28 19:31
*/
public enum SqlOperateEnum {
/**
* sql 条件属性 =
*/
EQ,
/**
* sql 条件属性 !=
*/
NE,
/**
* sql 条件属性 >
*/
GT,
/**
* sql 条件属性 <
*/
LT,
/**
* sql 条件属性 =
*/
GE,
/**
* sql 条件属性 =
*/
LE,
/**
* sql 条件属性 like
*/
LIKE,
/**
* sql 条件属性 in
*/
IN,
/**
* sql 条件属性 为空
*/
ISNULL,
/**
* sql 条件属性 不为空
*/
ISNOTNULL;
SqlOperateEnum() {
}
public static SqlOperateEnum fromString(String value) {
return valueOf(value.toLowerCase());
}
}
第二步:定义自定查询实体
package com.miaomiao.common.sql;
import com.miaomiao.common.enums.SqlConnectEnum;
import com.miaomiao.common.enums.SqlOperateEnum;
import java.io.Serializable;
/**
* @program: miaomiao
* @description:
* @author: lzy
* @create: 2020-11-02 17:06
*/
public class SqlFilter implements Serializable {
private static final long serialVersionUID = 1L;
private String property;
private Object value;
private SqlConnectEnum sqlConnectEnum;
private SqlOperateEnum sqlOperateEnum;
public SqlFilter() {
}
public SqlFilter(SqlConnectEnum sqlConnectEnum, String property, SqlOperateEnum sqlOperateEnum, Object value) {
this.sqlConnectEnum = sqlConnectEnum;
this.property = property;
this.sqlOperateEnum = sqlOperateEnum;
this.value = value;
}
public static SqlFilter andEq(String property, Object value) {
return new SqlFilter(SqlConnectEnum.AND, property, SqlOperateEnum.EQ, value);
}
public static SqlFilter orEq(String property, Object value) {
return new SqlFilter(SqlConnectEnum.OR, property, SqlOperateEnum.EQ, value);
}
public static SqlFilter andNe(String property, Object value) {
return new SqlFilter(SqlConnectEnum.AND, property, SqlOperateEnum.NE, value);
}
public static SqlFilter orNe(String property, Object value) {
return new SqlFilter(SqlConnectEnum.OR, property, SqlOperateEnum.NE, value);
}
public static SqlFilter andGt(String property, Object value) {
return new SqlFilter(SqlConnectEnum.AND, property, SqlOperateEnum.GT, value);
}
public static SqlFilter orGt(String property, Object value) {
return new SqlFilter(SqlConnectEnum.OR, property, SqlOperateEnum.GT, value);
}
public static SqlFilter andLt(String property, Object value) {
return new SqlFilter(SqlConnectEnum.AND, property, SqlOperateEnum.LT, value);
}
public static SqlFilter orLt(String property, Object value) {
return new SqlFilter(SqlConnectEnum.OR, property, SqlOperateEnum.LT, value);
}
public static SqlFilter andGe(String property, Object value) {
return new SqlFilter(SqlConnectEnum.AND, property, SqlOperateEnum.GE, value);
}
public static SqlFilter orGe(String property, Object value) {
return new SqlFilter(SqlConnectEnum.OR, property, SqlOperateEnum.GE, value);
}
public static SqlFilter andLe(String property, Object value) {
return new SqlFilter(SqlConnectEnum.AND, property, SqlOperateEnum.LE, value);
}
public static SqlFilter orLe(String property, Object value) {
return new SqlFilter(SqlConnectEnum.OR, property, SqlOperateEnum.LE, value);
}
public static SqlFilter andLike(String property, Object value) {
return new SqlFilter(SqlConnectEnum.AND, property, SqlOperateEnum.LIKE, value);
}
public static SqlFilter orLike(String property, Object value) {
return new SqlFilter(SqlConnectEnum.OR, property, SqlOperateEnum.LIKE, value);
}
public static SqlFilter andIn(String property, Object value) {
return new SqlFilter(SqlConnectEnum.AND, property, SqlOperateEnum.IN, value);
}
public static SqlFilter orIn(String property, Object value) {
return new SqlFilter(SqlConnectEnum.OR, property, SqlOperateEnum.IN, value);
}
public static SqlFilter andIsNull(String property) {
return new SqlFilter(SqlConnectEnum.AND, property, SqlOperateEnum.ISNULL, (Object)null);
}
public static SqlFilter orIsNull(String property) {
return new SqlFilter(SqlConnectEnum.OR, property, SqlOperateEnum.ISNULL, (Object)null);
}
public static SqlFilter andIsNotNull(String property) {
return new SqlFilter(SqlConnectEnum.OR, property, SqlOperateEnum.ISNOTNULL, (Object)null);
}
public static SqlFilter orIsNotNull(String property) {
return new SqlFilter(SqlConnectEnum.OR, property, SqlOperateEnum.ISNOTNULL, (Object)null);
}
public String getProperty() {
return property;
}
public void setProperty(String property) {
this.property = property;
}
public Object getValue() {
return value;
}
public void setValue(Object value) {
this.value = value;
}
public SqlConnectEnum getSqlConnectEnum() {
return sqlConnectEnum;
}
public void setSqlConnectEnum(SqlConnectEnum sqlConnectEnum) {
this.sqlConnectEnum = sqlConnectEnum;
}
public SqlOperateEnum getSqlOperateEnum() {
return sqlOperateEnum;
}
public void setSqlOperateEnum(SqlOperateEnum sqlOperateEnum) {
this.sqlOperateEnum = sqlOperateEnum;
}
}
第三步:在基础实体对象通过继承sqlHelp类转成specification对象方法
package com.miaomiao.common.model;
/**
* BasePO
*
* @author lzy
*/
public class BasePo extends SqlHelp {
/**
* 获取按实体参数进行查询的specification
* @Param 无
* return specification
*/
public Specification toSpecification() {
return getSpecification(this);
}
/**
* 获取按过滤参数和实体参数进行查询的specification
* @Param sqlFilter
* return specification
*/
public Specification toSpecification(SqlFilter sqlFilter) {
List list = Arrays.asList(sqlFilter);
return toSpecification(list);
}
/**
* 获取按过滤参数进行查询的specification
* @Param sqlFilters
* return specification
*/
public Specification toSpecification(List sqlFilters) {
return getSpecificationBySqlFilter(this, sqlFilters);
}
}
第四步:编写SqlHelp解析类
package com.miaomiao.common.sql;
import com.miaomiao.common.enums.SqlConnectEnum;
import com.miaomiao.common.model.BasePo;
import com.miaomiao.common.utils.SqlUtils;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.util.CollectionUtils;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
/**
* @program: miaomiao
* @description:
* @author: lzy
* @create: 2020-11-04 11:18
*/
public class SqlHelp {
/**
* 根据sqlFilters封装Specification
* @Param basePo 基础实体类
* @Param sqlFilters 过滤条件集合
* return 处理结果
*/
public Specification getSpecificationBySqlFilter(BasePo basePo, List sqlFilters) {
// sqlFilters为空,执行无过滤查询
if (CollectionUtils.isEmpty(sqlFilters)){
return getSpecification(basePo);
}
return (Specification) (root, criteriaQuery, criteriaBuilder) -> {
// 获取所有类属性
List fields = SqlUtils.getAllField(basePo.getClass());
// 定义and或者or数组
List andList = new ArrayList();
List orList = new ArrayList();
// 过滤掉自定义参数字段
List filterFields = SqlUtils.getFilterField(fields, sqlFilters);
// 循环实体类属性字段查询
for (Field field : filterFields) {
try {
field.setAccessible(true);
Path
第五步:编写SqlHelp工具类
package com.miaomiao.common.utils;
import com.alibaba.fastjson.JSON;
import com.miaomiao.common.model.BasePO;
import com.miaomiao.common.sql.SqlFilter;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;
/**
* @program: miaomiao
* @description:
* @author: lzy
* @create: 2020-11-02 17:25
*/
public class SqlUtils {
/**
* 找到类所有字段包括父类的集合
* @param clazz 类Class
* @return 类所有字段的集合
*/
public static List getAllField(Class> clazz) {
List fieldList = new ArrayList<>();
Field[] fields = clazz.getDeclaredFields();
if (fields.length != 0) {
fieldList.addAll(Arrays.asList(fields));
}
Class> superclass = clazz.getSuperclass();
// 如果父类是Object, 直接返回
if (superclass == Object.class) {
return fieldList;
}
// 递归获取所有的父级的Field
List superClassFieldList = getAllField(superclass);
if (!superClassFieldList.isEmpty()) {
superClassFieldList.stream()
// 去除重复字段
.filter(field -> !fieldList.contains(field))
.forEach(fieldList::add);
}
return fieldList;
}
/**
* 过滤Field
* @Param sqlFilters
* @Param fields
* return 处理结果
*/
public static List getFilterField(List fields, List sqlFilters){
// 获取SqlFilter所有属性字段
List fieldList = sqlFilters.stream().map(SqlFilter::getProperty).distinct().collect(Collectors.toList());
Iterator iterator = fields.iterator();
while (iterator.hasNext()){
Field field = iterator.next();
field.setAccessible(true);
if (fieldList.contains(field.getName())){
iterator.remove();
}
}
return fields;
}
}
第六步:PO要继承基础Po类,并且要实现泛型(不可缺漏)
第五步:用法和效果
总结:
反射真香!