1、查詢關(guān)系匹配枚舉
package com.xx.xxx.enums;
/**
* @description: 查詢條件關(guān)系匹配
* @author: fangzhao
* @create: 2020/4/1 15:34
* @update: 2020/4/1 15:34
*/
public enum MatchCondition {
/**
* equal-相等嗦枢,notEqual-不等于攀芯,like-模糊匹配,notLike-文虏,
* gt-大于侣诺,ge-大于等于,lt-小于氧秘,le-小于等于年鸳,
* greaterThan-大于,greaterThanOrEqualTo-大于等于丸相,lessThan-小于搔确,lessThanOrEqualTo-小于等于
*/
EQUAL,
NOT_EQUAL,
LIKE,
NOT_LIKE,
GT,
GE,
LT,
LE,
GREATER_THAN,
GREATER_THAN_OR_EQUAL_TO,
LESS_THAN,
LESS_THAN_OR_EQUAL_TO
}
2、查詢條件注解
package com.xx.xxx.annotations;
import com.xx.xxx.enums.MatchCondition;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @description: 查詢條件
* @author: fangzhao
* @create: 2020/4/1 15:34
* @update: 2020/4/1 15:34
*/
@Target({ElementType.FIELD,ElementType.CONSTRUCTOR })
@Retention(RetentionPolicy.RUNTIME)
public @interface QueryCondition {
/**
* 數(shù)據(jù)庫(kù)中字段名,默認(rèn)為空字符串,則Query類中的字段要與數(shù)據(jù)庫(kù)中字段一致
*/
String column() default "";
/**
* @see MatchCondition
*/
MatchCondition func() default MatchCondition.EQUAL;
/**
* object是否可以為null
*/
boolean nullable() default false;
/**
* 字符串是否可為空
*/
boolean emptyable() default false;
}
3灭忠、分頁(yè)工具類
package com.xx.xxx.utils;
import com.xx.xxx.annotations.QueryCondition;
import com.xx.xxx.vo.OrderInfoVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.lang.Nullable;
import org.springframework.util.CollectionUtils;
import javax.persistence.criteria.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.util.*;
/**
* @description: 分頁(yè)和排序工具類
* @author: fangzhao
* @create: 2020/3/24 13:09
* @update: 2020/3/24 13:09
*/
@Slf4j
public class PageUtil<T> {
/**
* 描述:排序處理膳算,默認(rèn)id降序
*
* @param orderInfos,這里也可以使用可變長(zhǎng)度的參數(shù)列表 OrderInfoVo...
* @return org.springframework.data.domain.Sort
* @author fangzhao at 2020/11/13 9:22
*/
public static Sort getSortOrder(List<OrderInfoVo> orderInfos) {
List<Sort.Order> sortOrders = new ArrayList<>();
if (null == orderInfos || CollectionUtils.isEmpty(orderInfos)) {
Sort.Order sortOrder = new Sort.Order(Sort.Direction.DESC, "id");
sortOrders.add(sortOrder);
} else {
for (OrderInfoVo order : orderInfos) {
String orderField = order.getOrderField();
String orderType = order.getOrderType();
Sort.Order sortOrder = new Sort.Order("asc".equalsIgnoreCase(orderType) ? Sort.Direction.ASC : Sort.Direction.DESC, orderField);
sortOrders.add(sortOrder);
}
}
return Sort.by(sortOrders);
}
/**
* 描述:生成查詢條件
*
* @param rangeTime
* @param timeStart
* @param timeEnd
* @return org.springframework.data.jpa.domain.Specification<T>
* @author fangzhao at 2020/11/13 9:24
*/
public Specification<T> specification(String rangeTime, LocalDateTime timeStart, LocalDateTime timeEnd) {
return (Specification<T>) (root, criteriaQuery, criteriaBuilder) -> {
// 增加篩選條件
Predicate predicate = criteriaBuilder.conjunction();
// 起始日期
if (null != timeStart) {
predicate.getExpressions().add(criteriaBuilder.greaterThanOrEqualTo(root.get(rangeTime).as(LocalDateTime.class), timeStart));
}
// 結(jié)束日期
if (null != timeEnd) {
predicate.getExpressions().add(criteriaBuilder.lessThan(root.get(rangeTime).as(LocalDateTime.class), timeEnd));
}
return predicate;
};
}
/**
* @description: 根據(jù)注解信息生成查詢條件
* @creater: fangzhao
* @updater:
* @create: 2020/3/24 13:09
* @update: 2020/3/24 13:09
* @Param: request entity
* @return:
*/
public Specification specification(T request, T entity) {
List<Field> reqFieldList = getAllFieldsWithRoot(request.getClass());
Map<T, List<Field>> map = new HashMap<>(16);
map.put(request, reqFieldList);
for (Field field : reqFieldList) {
if (field.getType().equals(entity.getClass())) {
List<Field> entityFieldList = getAllFieldsWithRoot(field.getType());
map.put(entity, entityFieldList);
break;
}
}
return getSpecification(request, map);
}
/**
* 描述:根據(jù)注解信息生成查詢條件
*
* @param request
* @return org.springframework.data.jpa.domain.Specification
* @author fangzhao at 2020/4/9 10:00
*/
public Specification specification(T request) {
List<Field> reqFieldList = getAllFieldsWithRoot(request.getClass());
Map<T, List<Field>> map = new HashMap<>(4);
map.put(request, reqFieldList);
return getSpecification(request, map);
}
/**
* 描述:獲取類clazz的所有Field弛作,包括其父類的Field
*
* @param clazz
* @return java.util.List<java.lang.reflect.Field>
* @author fangzhao at 2020/4/9 10:00
*/
private List<Field> getAllFieldsWithRoot(Class<?> clazz) {
List<Field> fieldList = new ArrayList<>();
Field[] dFields = clazz.getDeclaredFields();
if (ArrayUtils.isNotEmpty(dFields)) {
fieldList.addAll(Arrays.asList(dFields));
}
// 若父類是Object涕蜂,則直接返回當(dāng)前Field列表
Class<?> superClass = clazz.getSuperclass();
if (Object.class == superClass) {
return Arrays.asList(dFields);
}
// 遞歸查詢父類的field列表
List<Field> superFields = getAllFieldsWithRoot(superClass);
if (!CollectionUtils.isEmpty(superFields)) {
superFields.stream().
filter(field -> !fieldList.contains(field)).
forEach(field -> fieldList.add(field));
}
return fieldList;
}
/**
* 描述:生成查詢條件
*
* @param request
* @param map
* @return org.springframework.data.jpa.domain.Specification
* @author fangzhao at 2020/4/9 9:59
*/
private Specification getSpecification(T request, Map<T, List<Field>> map) {
Specification<T> specification = new Specification<T>() {
@Nullable
@Override
public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
Predicate predicate = criteriaBuilder.conjunction();
if (null == map || CollectionUtils.isEmpty(map)) {
return predicate;
}
Set objects = map.keySet();
for (Object obj : objects) {
List<Field> fieldList = map.get(obj);
for (Field field : fieldList) {
QueryCondition qc = field.getAnnotation(QueryCondition.class);
if (null == qc) {
continue;
}
// 如果主注解上colume為默認(rèn)值"",則以field為準(zhǔn)
String column = StringUtils.isNotBlank(qc.column()) ? qc.column() : field.getName();
field.setAccessible(true);
Object value = null;
// 默認(rèn)getter方法獲取屬性值映琳,如果是boolean基本類型宇葱,設(shè)置為is
String getValueType = "boolean".equals(field.getGenericType().toString()) ? "is" : "get";
char[] chars = field.getName().toCharArray();
chars[0] -= 32;
try {
Method method = obj.getClass().getMethod(getValueType + new String(chars));
value = method.invoke(obj);
} catch (Exception e) {
log.error("dataMiddle tools: {}", e.getMessage());
}
// 如果值為null,且注解未標(biāo)注nullable刊头,跳過(guò)
if (null == value && !qc.nullable()) {
continue;
}
if (null != value && String.class.isAssignableFrom(value.getClass())) {
String s = (String) value;
// 如果值為""黍瞧,且注解未標(biāo)注emptyable怀跛,跳過(guò)
if ("".equals(s) && !qc.emptyable()) {
continue;
}
}
// 通過(guò)注解上func屬性吸耿,構(gòu)建路徑表達(dá)式
Path path = null;
try {
path = root.get(column);
} catch (IllegalArgumentException e) {
log.error("dataMiddle tools: {}", e.getMessage());
}
if (null != path) {
switch (qc.func()) {
case EQUAL:
predicate.getExpressions().add(criteriaBuilder.equal(path, value));
break;
case LIKE:
predicate.getExpressions().add(criteriaBuilder.like(path, "%" + value + "%"));
break;
case GE:
if (value instanceof LocalDateTime) {
predicate.getExpressions().add(criteriaBuilder.greaterThanOrEqualTo(path.as(LocalDateTime.class), (LocalDateTime) value));
}
break;
case LT:
if (value instanceof LocalDateTime) {
predicate.getExpressions().add(criteriaBuilder.lessThan(path.as(LocalDateTime.class), (LocalDateTime) value));
}
break;
default:
}
}
}
}
return predicate;
}
};
return specification;
}
}
4早抠、使用
public Page<DataStandardTypeEntity> getPage(DataStandardTypeReqVO request) {
Sort sortOrder = PageUtil.getSortOrder(request.getOrderInfo());
Pageable pageable = PageRequest.of(request.getPageNum() - 1, request.getPageSize(), sortOrder);
Specification<DataStandardTypeEntity> specification = new PageUtil<>().specification(request, request.getEntity());
return dataStandardTypeRepository.findAll(specification, pageable);
}
DataStandardTypeReqVO 字段添加響應(yīng)的注解
package com.xx.xxx.vo;
import com.yss.datamiddle.po.DataStandardTypeEntity;
/**
* @description: 數(shù)據(jù)標(biāo)準(zhǔn)類型請(qǐng)求類
* @author: fangzhao
* @create: 2020/3/24 13:09
* @update: 2020/3/24 13:09
*/
public class DataStandardTypeReqVO extends RangeRequest{
private DataStandardTypeEntity entity = new DataStandardTypeEntity();
public DataStandardTypeEntity getEntity() {
return entity;
}
public void setEntity(DataStandardTypeEntity entity) {
this.entity = entity;
}
}
package com.xxx.xxx.vo;
import com.xxx.xxx.annotations.QueryCondition;
import com.xxx.xxx.enums.MatchCondition;
import io.swagger.annotations.ApiModelProperty;
import org.springframework.format.annotation.DateTimeFormat;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
/**
* @ClassName RangeRequest
* @Description 請(qǐng)求范圍
* @Author fangzhao
* @Date 2020/3/18 16:07
*/
public class RangeRequest<T> extends PageInfo {
@ApiModelProperty(value = "創(chuàng)建時(shí)間", example = "2020-03-23 14:40:10", hidden = true)
@QueryCondition(func = MatchCondition.ge, column = "createTime")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTimeStart;
@ApiModelProperty(value = "創(chuàng)建時(shí)間", example = "2020-03-23 14:40:10", hidden = true)
@QueryCondition(func = MatchCondition.lt, column = "createTime")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTimeEnd;
@ApiModelProperty(value = "修改時(shí)間", example = "2020-03-23 14:40:10", hidden = true)
@QueryCondition(func = MatchCondition.ge, column = "modifyTime")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime modifyTimeStart;
@ApiModelProperty(value = "修改時(shí)間", example = "2020-03-23 14:40:10", hidden = true)
@QueryCondition(func = MatchCondition.lt, column = "modifyTime")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime modifyTimeEnd;
@ApiModelProperty(value = "有效期開始時(shí)間", example = "2020-03-23 14:40:10", hidden = true)
@QueryCondition(func = MatchCondition.ge, column = "validDate")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime validDateStart;
@ApiModelProperty(value = "有效期截止時(shí)間", example = "2020-03-23 14:40:10", hidden = true)
@QueryCondition(func = MatchCondition.lt, column = "validDate")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime validDateEnd;
@ApiModelProperty("排序信息")
private List<OrderInfoVo> orderInfo = new ArrayList<>();
}