巧用Lambda表达式获取对象属性名告别魔法值

在我们日常开发中,使用 MyBatis-Plus 写 SQL 执行的时候,难免会用到表字段,虽然 MyBatis-Plus 提供了 LambdaQueryWrapper 帮助我们使用 Lambda 方式调用对象属性名,但有的时候还是不免用到魔法值,当对象的属性名更改了之后,我们难免会漏掉,引发生产事故

1、定义支持序列化的 Function

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 同样是这样做的底层调用,这样我们就能使用 Lambda 表达式的方式获取对象属性名,不用写入魔法值,当属性名更改了之后,idea 开发工具会提醒我们,也能及时发现修改

如您在阅读中发现不足,欢迎留言!!!

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Asurplus

学如逆水行舟,不进则退

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值