私たちの日常の開発では、MyBatis-Plus を使用して SQL を記述して実行する場合、必然的にテーブル フィールドが使用されますが、MyBatis-Plus では、Lambda メソッドを使用してオブジェクトのプロパティ名を呼び出すのに役立つ LambdaQueryWrapper が提供されていますが、場合によっては依然としてマジック値が使用されます。 、オブジェクトの属性名が変更されると、必然的にそれを見逃して本番事故を引き起こします。
1. シリアル化をサポートする関数を定義する
import java.io.Serializable;
import java.util.function.Function;
/**
* 支持序列化的 Function
*
* @author miemie
* @since 2018-05-12
*/
@FunctionalInterface
public interface SFunction<T, R> extends Function<T, R>, Serializable {
}
これはMyBatis-Plusが提供する関数であり、呼び出し方法も非常にシンプルで、例えばUserDOというエンティティオブジェクトがあります。
public class UserDO {
private Long id;
private String name;
private Integer age;
private String phone;
}
呼び出しメソッドは次のとおりです。
SFunction<UserDO, Long> func = UserDO::getId;
2. 属性名を取得する
たとえば、上記の呼び出しメソッド UserDO::getId は「id」文字列を取得することを目的としており、次に、MyBatis-Plus が提供するツール クラスを使用して属性名を取得します。
import com.baomidou.mybatisplus.core.toolkit.LambdaUtils;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import org.apache.ibatis.reflection.property.PropertyNamer;
import java.beans.Introspector;
/**
* 获取属性名工具类
*
* @author asurplus
*/
public class FieldUtils {
/**
* 获取Java属性名
*
* @return userName
*/
public static <T, R> String getFieldName(SFunction<T, R> func) {
// 获取 lambda 表达式实现方法的名称
String fieldName = LambdaUtils.extract(func).getImplMethodName();
// 去掉前缀:get,is
fieldName = PropertyNamer.methodToProperty(fieldName);
// 首字母小写
return Introspector.decapitalize(fieldName);
}
}
呼び出し方法:
public static void main(String[] args) {
String fieldName = FieldUtils.getFieldName(UserDO::getId);
System.out.println(fieldName);
}
出力:
3. データベースフィールド名を取得します。
上記で属性名を取得したので、フィールド名をキャメルケースにして下線操作を行います。
/**
* 获取数据库字段名
*
* @return user_name
*/
public static <T, R> String getColumnName(SFunction<T, R> func) {
String fieldName = getFieldName(func);
// 转下划线
return StrUtil.toUnderlineCase(fieldName);
}
ここの StrUtil.toUnderlineCase() は、hutool ツール パッケージのツール クラスを使用して実装されています。
呼び出し方法:
public static void main(String[] args) {
String fieldName = FieldUtils.getColumnName(UserDO::getUserName);
System.out.println(fieldName);
}
出力:
4. ボトムコール
上記では、MyBatis-Plus の LambdaUtils ツール クラスを使用してオブジェクト属性名を取得しましたが、MyBatis-Plus を導入せずに、どのように取得するのでしょうか?
/**
* 获取Java属性名
*
* @return userName
*/
public static <T, R> String getFieldName(SFunction<T, R> func) {
try {
Method method = func.getClass().getDeclaredMethod("writeReplace");
method.setAccessible(true);
SerializedLambda serializedLambda = (SerializedLambda) method.invoke(func);
String fieldName = serializedLambda.getImplMethodName();
if (fieldName.startsWith("get")) {
fieldName = fieldName.substring(3);
}
if (fieldName.startsWith("is")) {
fieldName = fieldName.substring(2);
}
// 首字母小写
return fieldName.substring(0, 1).toLowerCase() + fieldName.substring(1);
} catch (ReflectiveOperationException e) {
throw new RuntimeException(e);
}
}
MyBatis-Plus の LambdaUtils も同じ基本的な呼び出しを使用するため、ラムダ式を使用してマジック値を書かずにオブジェクトの属性名を取得できます。属性名が変更されると、アイデア開発ツールが通知し、検出できます。すぐに変化する
読んでいて不備がある場合は、メッセージを残してください。!!