自定义lamba表达式属性名转字段名方法(mybaits-plus多表连接查询,无法使用lamba表达式指定获取字段名的解决办法)

自定义lamba表达式属性名转字段名方法(mybaits-plus多表连接查询,无法使用lamba表达式指定获取字段名的解决办法)

背景

使用mybatis-plus进行多表连接查询时需要自定义sql,可以将mybatis-plus的条件构造器传入进去,生成选择语句与筛选语句(如下图)

image-20211114153920921

让mybatis-plus条件构造器生成查询条件和选择语句可以使查询更加灵活,

mybatis-plus条件构造器 支持lamba表达式,但仅限于QueryWrapper管理的类

image-20211114154255014

如果是多表查询,想要查另一个表的字段,只能使用传入字符串的方式。

image-20211114154354076

如果两个表都同时有name这个字段,我们还需加上前缀,而LambaQueryWrapper是无法传入前缀的,我们只能传入字符串,这样极易产生魔法值导致项目不易维护。

经过思考,我们可以复用mybait-plus将属性转为表中对应字段的方法,在其基础上进行扩展,最终达到能任何实体类都能通过lamba表达式获取对应数据库字段,同时可以为其配置表前缀的目的。

实现

自定义字段转换器类ColumnResolver

package marchsoft.modules.linglu.common.utils;

import com.baomidou.mybatisplus.core.conditions.AbstractLambdaWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;

import java.util.Arrays;

import static java.util.stream.Collectors.joining;

/**
 * @author lixiangxiang
 * @description 字段转换器
 */
public class ColumnResolver<T> extends AbstractLambdaWrapper<T, ColumnResolver<T>> {

    @Override
    protected ColumnResolver<T> instance() {
        return null;
    }

    @SafeVarargs
    @Override
    public final String columnsToString(SFunction<T, ?>... columns) {
        return super.columnsToString(columns);
    }

    /**
     * description: 实体类属性转数据库字段名+前缀 批量
     *
     * @author: lixiangxiang
     * @param prefix 前缀
     * @param columns 字段
     * @return java.lang.String
     */
    @SafeVarargs
    public final String columnsToStringWithPrefix(String prefix, SFunction<T, ?>... columns) {
        StringBuilder stringBuilder = new StringBuilder();
        return Arrays.stream(columns).map(i -> columnsToStringWithPrefix(prefix,i)).collect(joining(StringPool.COMMA));
    }

    /**
     * description: 实体类属性转数据库字段名+前缀
     *
     * @author: lixiangxiang
     * @param prefix 前缀
     * @param column 字段
     * @return java.lang.String
     */
    public final String columnsToStringWithPrefix(String prefix, SFunction<T, ?> column) {
        return prefix + StringPool.DOT + super.columnToString(column);
    }

    @SafeVarargs
    @Override
    public final String columnsToString(boolean onlyColumn, SFunction<T, ?>... columns) {
        return super.columnsToString(onlyColumn, columns);
    }

    @Override
    public String columnToString(SFunction<T, ?> column) {
        return super.columnToString(column);
    }

    @Override
    public String columnToString(SFunction<T, ?> column, boolean onlyColumn) {
        return super.columnToString(column, onlyColumn);
    }
}

使用实例

案例描述,业务需要筛选出部门id 为 3 的用户user的姓名、年龄和部门名称,部门dpet在另一张关系表中存储。用户表使用别名u,部门表使用别名d

service层代码

QueryWrapper<User> queryWrapper = new QueryWrapper<Course>
ColumnResolver<Job> DeptResolver = new ColumnResolver<>();
ColumnResolver<Job> UserResolver = new ColumnResolver<>();
String userPrefix = "u";
String deptPrefix = "d";
queryWrapper.select(UserResolver.columnsToStringWithPrefix(userPrefix,User:;getName,User::getAge),
                    DeptResolver.columnsToStringWithPrefix(deptPrefix,Dept::getName));
Integer deptId = 3;
queryWrpper.eq(DeptReslover.columnsToStringWithPrefix("t",Dept::id),deptId);
userMapper.selectUserByDeptId(queryWrapper);

Mapper层代码

@Select({"select ${ew.sqlSelect}",
        "from user u",
        "left join dept d",
        "on u.deptId = d.id",
        "${ew.customSqlSegment}"})
selectUserByDeptId(@Param(Constants.WRAPPER)QueryWrapper queryWrapper)

前缀可以用枚举定义,为每个表指定特定的别名,保证写的sql语句中的表别名与枚举类中的一致即可。

(还有一种方案,不要让表指定别名,统一用表名来访问,枚举中定义表名,这样能最大程度上确保自己不会写错。)

注意:如果字段需要加前缀,请使用columnsToStringWithPrefix方法,prefix为sql语句中为表指定的别名,必须保证prefix与表别名一致

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值