jpa 自定义注解 进行多字段 范围/精确查询

记录一波 同事写的优秀代码 @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);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值