Mongodb数据库基于spring-boot-starter-data-mongodb的查询工具

发布时间 2023-08-25 15:33:59作者: 扰扰
/**
 * 字段注解
 */
public @interface BuilderField {
    /**
     * 对应的数据库字段名称
     * @return
     */
    String name();
}
import lombok.SneakyThrows;

import java.io.Serializable;
import java.lang.invoke.SerializedLambda;
import java.lang.reflect.Method;
import java.util.function.Function;

@FunctionalInterface
public interface BuilderFunction<T, R> extends Function<T, R>, Serializable {
    @SneakyThrows
    default String getFieldName() {
        String methodName = getMethodName();
        if (methodName.startsWith("get")) {
            methodName = methodName.substring(3);
        }
        return methodName;
    }

    @SneakyThrows
    default String getMethodName() {
        return getSerializedLambda().getImplMethodName();
    }

    @SneakyThrows
    default Class<?> getFieldClass() {
        return getReturnType();
    }

    @SneakyThrows
    default SerializedLambda getSerializedLambda() {
        Method method = getClass().getDeclaredMethod("writeReplace");
        method.setAccessible(true);
        return (SerializedLambda) method.invoke(this);
    }

    @SneakyThrows
    default Class<?> getReturnType() {
        SerializedLambda lambda = getSerializedLambda();
        Class<?> className = Class.forName(lambda.getImplClass().replace("/", "."));
        Method method = className.getMethod(getMethodName());
        return method.getReturnType();
    }
}
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;

import java.beans.Introspector;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @Description : 查询封装
 * @Author : cxw
 * @Date : 2023/8/7 13:13
 * @Version : 1.0
 **/
public class BuilderQuery<T>  {

    private static Pattern humpPattern = Pattern.compile("[A-Z]");

    private static final Pattern GET_PATTERN = Pattern.compile("^get[A-Z].*");
    private static final Pattern IS_PATTERN = Pattern.compile("^is[A-Z].*");

    private static Logger logger = LoggerFactory.getLogger(BuilderQuery.class);

    private Field[] fields;

    private String className;

    private Class _clazz;


    Criteria criteria =null;

    public BuilderQuery(Class<?> clazz) {
        fields = clazz.getDeclaredFields();
        className=clazz.getName();
        _clazz=clazz;
    }

    /**
     * 精准匹配 field=val 的sql
     * @param func 类的字段名get方法
     * @param val 类对应的字段值
     * @return
     */
    public BuilderQuery eq(BuilderFunction<T, Object> func,Object val) throws Exception {
        String field = getFieldName(func.getMethodName());
        String _field = getSQLField(field);
        if(criteria==null){
            criteria=Criteria.where(_field).is(val);
        }else {
            criteria.and(_field).is(val);
        }
        return this;
    }

    /**
     * in 查询
     * @param func 类的字段名get方法
     * @param val 类对应的字段值
     * @return
     */
    public BuilderQuery in(BuilderFunction<T, Object> func, List<Object> val) throws Exception {
        String field = getFieldName(func.getMethodName());
        String _field = getSQLField(field);
        if(criteria==null){
            criteria=Criteria.where(_field).in(val);
        }else {
            criteria.and(_field).in(val);
        }
        return this;
    }

    /**
     * like模糊 查询
     * @param func 类的字段名get方法
     * @param val 类对应的字段值
     * @return
     */
    public BuilderQuery like(BuilderFunction<T, Object> func, String val,Boolean allLike) throws Exception {
        String field = getFieldName(func.getMethodName());
        String _field = getSQLField(field);
        if(criteria==null){
            criteria=Criteria.where(_field).regex(val);
        }else {
            criteria.and(_field).regex(val);
        }
        return this;
    }

    /**
     * 大于查询
     * @param func 类的字段名get方法
     * @param val 类对应的字段值
     * @return
     */
    public BuilderQuery gt(BuilderFunction<T, Object> func, String val) throws Exception {
        String field = getFieldName(func.getMethodName());
        String _field = getSQLField(field);
        if(criteria==null){
            criteria=Criteria.where(_field).gt(val);
        }else {
            criteria.and(_field).gt(val);
        }
        return this;
    }

    /**
     * 小于查询
     * @param func 类的字段名get方法
     * @param val 类对应的字段值
     * @return
     */
    public BuilderQuery lt(BuilderFunction<T, Object> func, String val) throws Exception {
        String field = getFieldName(func.getMethodName());
        String _field = getSQLField(field);
        if(criteria==null){
            criteria=Criteria.where(_field).lt(val);
        }else {
            criteria.and(_field).lt(val);
        }
        return this;
    }


    /**
     * 生成字段
     * @param field
     * @return
     * @throws Exception
     */
    private String getSQLField(String field) throws Exception {
        for (Field field1 : fields) {
            if(field1.getName().equals(field)){
                // 获取字段上的注解对象
                Annotation[] annotations =field1.getDeclaredAnnotations();
                String tableField = hasBuilderField(annotations);
                if(tableField==null)tableField=humpToLine(field);
                return tableField;
            }
        }
        throw new Exception("当前类:"+className+"不存在字段:"+field+"");
    }

    /**
     * 判断是否存在BuilderField注解
     * @param annotations
     * @return
     */
    public static String hasBuilderField(Annotation[] annotations) {
        if(annotations==null||annotations.length==0)return null;
        for (Annotation annotation : annotations) {
            if(annotation instanceof BuilderField){
                return ((BuilderField) annotation).name();
            }
        }
        return null;
    }


    /**
     * 驼峰转下划线
     * @param str
     * @return
     */
    public static String humpToLine(String str){
        Matcher matcher = humpPattern.matcher(str);
        StringBuffer sb = new StringBuffer();
        while(matcher.find()){
            matcher.appendReplacement(sb, "_"+matcher.group(0).toLowerCase());
        }
        matcher.appendTail(sb);
        return sb.toString();
    }

    /**
     * 方法名转字段名
     * @param methodName
     * @return
     */
    private String getFieldName(String methodName){
        // 对于非标准变量生成的Get方法这里可以直接抛出异常,或者打印异常日志
        if (GET_PATTERN.matcher(methodName).matches()) {
            methodName = methodName.substring(3);
        } else if (IS_PATTERN.matcher(methodName).matches()) {
            methodName = methodName.substring(2);
        }
        return Introspector.decapitalize(methodName);
    }

    /**
     * 获取query
     * @return
     */
    public Query getQuery() {
        Query query = new Query(criteria);
        return query;
    }

    /***
     * 使用案例
     *
     *         BuilderQuery<OrgV2DO> builderQuery=new BuilderQuery(OrgV2DO.class);
     *         builderQuery.eq(OrgV2DO::getId,"123213");
     *         builderQuery.eq(OrgV2DO::getLastModifiedBy,"123213");
     *         String org = builderQuery.getQuery();
     *         System.out.println(org);
     *
     * ****/
}