记录一波 同事写的优秀代码 @Tyler
在进行 很多条件筛选条件查询时候,查询条件特别多,可以利用反射进行查询条件的拼接,使用注解区分精确匹配和范围匹配
@Eq 用于精确匹配
@Target({ElementType.PARAMETER, ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Eq {
}
@Between 用于范围匹配
type 可以区别 Integer (数值)和date(日期类型的区别)
@Target({ElementType.PARAMETER, ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Between {
String type();
String datePattern();
}
对应的实体类
@Data
public class UserResourcesRequest extends PageRequest {
@ApiModelProperty("id")
private String id;
@ApiModelProperty("车牌")
@Eq
private String plateNumber;
@ApiModelProperty("用途")
@Eq
private String usage;
@ApiModelProperty("级别")
@Eq
private String level;
@ApiModelProperty("品牌")
@Eq
private String brand;
@ApiModelProperty("马力")
@Between(type = "Integer",datePattern = "")
private String horsepower;
@ApiModelProperty("驱动形式")
@Eq
private String driverType;
@ApiModelProperty("档位")
@Eq
private String gears;
@ApiModelProperty("燃料")
@Eq
private String fuel;
@ApiModelProperty("排放等级")
@Eq
private String emissionLevel;
@ApiModelProperty(value = "生产日期")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm", timezone="GMT+8")
@Between(type = "Date",datePattern = "yyyy-MM-dd")
private Integer productionTime;
@ApiModelProperty("年运营里程")
@Eq
private String mileage;
@ApiModelProperty("载重")
@Eq
private String load;
}
反射构建查询代码:
public class ConditionBuild {
public static List<Predicate> queryConditionWrapper(Root<?> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder,Object querySource){
//获取查询类所有字段
Field[] fields =querySource.getClass().getDeclaredFields();
List<Predicate> predicates = Lists.newArrayList();
try {
for (Field field : fields) {
field.setAccessible(true);
//用于精确匹配查询
if (field.isAnnotationPresent(Eq.class)){
if (ObjectUtils.isNotEmpty(field.get(querySource))) {
try {
predicates.add(criteriaBuilder.and(criteriaBuilder.equal(root.get(field.getName()).as(field.getType()), field.get(querySource))));
} catch (java.lang.IllegalArgumentException e){
continue;
}
}
} else if (field.isAnnotationPresent(Between.class)){
Between between = field.getAnnotation(Between.class);
// 用于日期范围查询
if ("Date".equals(between.type())){
if (ObjectUtils.isNotEmpty(field.get(querySource))) {
Date currentDate = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Calendar cal = Calendar.getInstance();
cal.add(Calendar.MONTH, -((Integer) field.get(querySource)));
predicates.add(criteriaBuilder.and(criteriaBuilder.between(root.get(field.getName()).as(String.class), sdf.format(cal.getTime()), sdf.format(currentDate))));
}
}
//用于数值的范围查询
if ("Integer".equals(between.type())){
if (ObjectUtils.isEmpty(field.get(querySource)))continue;
String range = (String) field.get(querySource);
String[] strings = range.split("~");
if (strings.length==1 && StringUtils.isNotEmpty(strings[0])){
predicates.add(criteriaBuilder.and(criteriaBuilder.gt(root.get(field.getName()).as(Integer.class), Integer.parseInt(strings[0]))));
} else if (strings.length==2){
predicates.add(criteriaBuilder.and(criteriaBuilder.between(root.get(field.getName()).as(Integer.class), Integer.parseInt(strings[0]), Integer.parseInt(strings[1]))));
}
}
}
}
return predicates;
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
}
使用
Specification<UserResource> specification = (root, query, criteriaBuilder) -> {
List<Predicate> predicates = Lists.newArrayList();
predicates = ConditionBuild.queryConditionWrapper(root, query, criteriaBuilder,userResourcesRequest);
return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
};
Result<Page<UserResource>> pageResult = findPageList(userResourcesRequest.getPageNum(), userResourcesRequest.getPageSize(),specification);