看到mybatis-plus有个写法
原本我们应该写数据库列名”asset_id”。但是这种写法是一种魔数值,我们写代码应该尽量避免未经定义的变量出现在代码里。所以参考mbp,重复造了个轮子。
函数式接口
函数式接口是必须的,且函数式接口必须继承Serializable。
/*** @author zhy* @date 2021/1/2810:07*/@FunctionalInterfacepublic interface Func<T, R> extends Serializable {/*** 函数式接口的唯一方法* @param t* @throws* @return R* @author zhy* @date 2021/1/28 11:36*/R apply(T t);}
这样在方法中以函数式接口为参数,传入lambda表达式,就会将表达式生成成一个匿名类。继承Serializable的原因是,匿名类的将会多生成一个私有静态方法writeReplace()。而这个方法是关键,会返回一个SerializedLambda对象。SerializedLambda中有我们传进去的方法名称,例如getName 这种。通过get方法来解析出对应的类属性,和数据库字段
LambdaUtil
/**** @author zhy* @date 2021/1/2814:57*/@Slf4jpublic class LambdaUtil {/** 大写正则表达式 */private static Pattern upperPattern = Pattern.compile("[A-Z]");/** 下划线 */private static char underLine = '_';private LambdaUtil(){}/*** 获取lambda对应的属性名称* @param func* @throws* @return java.lang.String* @author zhy* @date 2021/1/28 10:51*/public static <T, R> String getPropertyName(Func<T, R> func) {String implMethodName = getImplMethodName(func);return methodToProperty(implMethodName);}/*** 获取lambda对应的数据库字段名称* 遵循通用定义:转化对应属性名,将属性名中的大写字母改为小写,并在前面加下划线* @param func* @throws* @return java.lang.String* @author zhy* @date 2021/1/28 10:51*/public static <T, R> String getSqlColumn(Func<T, R> func) {String implMethodName = getImplMethodName(func);String property = methodToProperty(implMethodName);return upperCharToUnderLine(property);}/*** 转化字符串中的大写字母为 _小写* @param param* @throws* @return java.lang.String* @author zhy* @date 2021/1/28 15:37*/private static String upperCharToUnderLine(String param){StringBuilder builder=new StringBuilder(param);Matcher mc=upperPattern.matcher(param);int i=0;while (mc.find()) {builder.replace(mc.start()+i, mc.end()+i, "_"+mc.group().toLowerCase());i++;}if(underLine == builder.charAt(0)){builder.deleteCharAt(0);}return builder.toString();}/*** 根据lambda表达式获取方法名称* @param func* @throws* @return java.lang.String* @author zhy* @date 2021/1/28 10:53*/private static <T, R> String getImplMethodName(Func<T, R> func){Method writeReplace = null;Object o = null;try {// 直接调用writeReplacewriteReplace = func.getClass().getDeclaredMethod("writeReplace");writeReplace.setAccessible(true);//反射调用o = writeReplace.invoke(func);} catch (Exception e) {log.error("",e);throw new CecServerException(CecServerCodeMessage.error(CecServerCodeMessageEnum.SYSTEM_EXECUTION_ERROR.getMessage()));}SerializedLambda lambda = (SerializedLambda) o;return lambda.getImplMethodName();}/*** 通过方法名称获取字段名称* @param methodName* @throws* @return java.lang.String* @author zhy* @date 2021/1/28 10:51*/private static String methodToProperty(String methodName) {if (methodName.startsWith("is")) {methodName = methodName.substring(2);} else {if (!methodName.startsWith("get") && !methodName.startsWith("set")) {throw new CecServerException("Error parsing property name '" + methodName + "'. Didn't start with 'is', 'get' or 'set'.");}methodName = methodName.substring(3);}if (methodName.length() == 1 || methodName.length() > 1 && !Character.isUpperCase(methodName.charAt(1))) {methodName = methodName.substring(0, 1).toLowerCase(Locale.ENGLISH) + methodName.substring(1);}return methodName;}}
