看到mybatis-plus有个写法
原本我们应该写数据库列名”asset_id”。但是这种写法是一种魔数值,我们写代码应该尽量避免未经定义的变量出现在代码里。所以参考mbp,重复造了个轮子。
函数式接口
函数式接口是必须的,且函数式接口必须继承Serializable。
/**
* @author zhy
* @date 2021/1/2810:07
*/
@FunctionalInterface
public 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
*/
@Slf4j
public 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 {
// 直接调用writeReplace
writeReplace = 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;
}
}