/** * 字段註解 */ 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); * * ****/ }