1、借助mybatis plus的方法
import com.baomidou.mybatisplus.core.toolkit.LambdaUtils;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.core.toolkit.support.SerializedLambda;
import lombok.SneakyThrows;
import org.apache.ibatis.reflection.property.PropertyNamer;
import java.lang.reflect.Field;
import java.util.Objects;
public class ObjectUtil {
/**
* 判断两个对象的某些字段的值是否相等
* @param newObj 新对象
* @param oldObj 旧对象
* @param functions 函数式接口数组
* @param <T> 泛型T
* @return 两个对象某些字段的值是否相等
*/
@SafeVarargs
@SneakyThrows
public static <T> boolean isSame(Object newObj,Object oldObj,SFunction<T,?>... functions){
for(SFunction<T,?> function:functions){
Field newField=newObj.getClass().getField(getField(function));
Field oldField=oldObj.getClass().getField(getField(function));
newField.setAccessible(true);
oldField.setAccessible(true);
if(!Objects.equals(newField.get(newObj),oldField.get(oldObj))){
return false;
}
}
return true;
}
/**
* 判断两个对象的某些字段的值是否相等
* @param newObj 新对象
* @param oldObj 旧对象
* @param fields 字段数组
* @return 是否相等
*/
@SneakyThrows
public static boolean isSame(Object newObj,Object oldObj,String... fields){
for(String filed:fields){
Field newField=newObj.getClass().getField(filed);
Field oldField=oldObj.getClass().getField(filed);
newField.setAccessible(true);
oldField.setAccessible(true);
if(!Objects.equals(newField.get(newObj),oldField.get(oldObj))){
return false;
}
}
return true;
}
/**
* 根据函数式接口的方法获取字段名称
* @param sFunction 函数式接口
* @param <T> 泛型T
* @return 字段名称
*/
public static <T> String getField(SFunction<T,?> sFunction){
return getColumn(LambdaUtils.resolve(sFunction));
}
/**
*
* @param serializedLambda 函数式接口的Lambda表达式
* @return 字段名
*/
public static String getColumn(SerializedLambda serializedLambda){
return PropertyNamer.methodToProperty(serializedLambda.getImplMethodName());
}
}
既可以直接输入字段名,也可以输入Lambda表达式获取字段名
2、自己手写函数式接口完成从Lambda表达式到字段名的解析
? ?2.1 先定义可以序列化的函数式接口
import java.io.Serializable;
import java.util.function.Function;
@FunctionalInterface
public interface MFunction<T, R> extends Function<T, R>, Serializable {
}
? 2.2 根据可以序列化的函数式接口解析字段名
? ? ? ? ?
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.property.PropertyNamer;
import java.lang.invoke.SerializedLambda;
import java.lang.reflect.Method;
@Slf4j
public class LambdaUtil {
/**
*
* @param serializedLambda 函数式接口的Lambda表达式
* @return 字段名
*/
public static String getColumn(SerializedLambda serializedLambda) {
return PropertyNamer.methodToProperty(serializedLambda.getImplMethodName());
}
/**
* 根据函数式接口获取字段名成
* @param func 函数式接口,例:User::getId()
* @param <T> 泛型T
* @param <R> 泛型R
* @return 字段名
*/
@SneakyThrows
private static <T, R> String getColumn(MFunction<T, R> func) {
// 直接调用writeReplace
Method writeReplace = func.getClass().getDeclaredMethod("writeReplace");
writeReplace.setAccessible(true);
//反射调用
Object sl = writeReplace.invoke(func);
return getColumn((java.lang.invoke.SerializedLambda) sl);
}
}