当前位置: 首页 > news >正文

MyBatis-Plus 动态字段映射工具:一行代码实现字段名动态转换

MyBatis-Plus 动态字段映射工具:一行代码实现字段名动态转换

痛点描述

在使用 MyBatis-Plus 开发时,我们经常遇到这样的场景:

// 前端传参:field=name, values=["张三","李四"]// 我们需要动态查询:WHERE name IN ('张三','李四')// 传统方式 - 硬编码queryWrapper.in("name",values);// 字段写死了,无法动态变化// Lambda方式 - 编译期固定queryWrapper.in(User::getName,values);// 同样无法动态变化

如果需求是前端动态传递字段名,以上两种方式都无能为力。比如:

  • 用户可选择按姓名工号部门等不同字段批量查询
  • 后台配置中心需要动态指定筛选字段
  • 报表工具需要根据配置动态分组

此时,我们需要一个工具:传入字段名字符串,返回对应的数据库列名。

解决方案

DynamicFieldUtil工具类,通过 MyBatis-Plus 的TableInfoHelper,实现实体类字段名到数据库列名的动态映射

核心代码

importcom.baomidou.mybatisplus.core.metadata.TableInfo;importcom.baomidou.mybatisplus.core.metadata.TableInfoHelper;importcom.baomidou.mybatisplus.core.metadata.TableFieldInfo;importjava.util.ArrayList;importjava.util.List;/** * MyBatis-Plus 动态字段映射工具 * 根据实体类字段名获取数据库列名,支持 @TableField 注解自动映射 * * @author Your Name * @since 2026-01-01 */publicclassDynamicFieldUtil{/** * 获取数据库列名 * * @param entityClass 实体类 Class(如 User.class) * @param propertyName 实体类字段名(如 "userName") * @return 数据库列名(如 "user_name"),找不到返回 null */publicstaticStringgetDbColumn(Class<?>entityClass,StringpropertyName){TableInfotableInfo=TableInfoHelper.getTableInfo(entityClass);if(tableInfo==null){returnnull;}// 1. 检查是否为主键if(tableInfo.getKeyProperty().equals(propertyName)){returntableInfo.getKeyColumn();}// 2. 遍历普通字段for(TableFieldInfofieldInfo:tableInfo.getFieldList()){if(fieldInfo.getProperty().equals(propertyName)){returnfieldInfo.getColumn();}}returnnull;}/** * 获取数据库列名(带异常提示) * * @param entityClass 实体类 * @param propertyName 字段名 * @return 数据库列名 * @throws IllegalArgumentException 字段不存在时抛出 */publicstaticStringgetDbColumnOrThrow(Class<?>entityClass,StringpropertyName){StringdbColumn=getDbColumn(entityClass,propertyName);if(dbColumn==null){List<String>availableFields=getAvailableFields(entityClass);thrownewIllegalArgumentException(String.format("实体类 %s 中找不到字段 '%s',可用字段: %s",entityClass.getSimpleName(),propertyName,String.join(", ",availableFields)));}returndbColumn;}/** * 获取实体类所有可用字段名 */publicstaticList<String>getAvailableFields(Class<?>entityClass){TableInfotableInfo=TableInfoHelper.getTableInfo(entityClass);if(tableInfo==null){returnnewArrayList<>();}List<String>fields=newArrayList<>();fields.add(tableInfo.getKeyProperty());// 主键tableInfo.getFieldList().forEach(f->fields.add(f.getProperty()));returnfields;}}

使用示例

1. 基础用法

@RestControllerpublicclassUserController{@AutowiredprivateUserServiceuserService;@GetMapping("/search")publicResultsearch(@RequestParamStringfield,@RequestParamList<String>values){// 1. 获取数据库列名StringdbColumn=DynamicFieldUtil.getDbColumn(User.class,field);if(dbColumn==null){returnResult.error("不支持的字段: "+field);}// 2. 构建查询QueryWrapper<User>wrapper=newQueryWrapper<>();wrapper.in(dbColumn,values);returnResult.success(userService.list(wrapper));}}

2. 带异常提示

@GetMapping("/search")publicResultsearch(@RequestParamStringfield,@RequestParamList<String>values){try{// 字段不存在会自动抛异常,并列出所有可用字段StringdbColumn=DynamicFieldUtil.getDbColumnOrThrow(User.class,field);QueryWrapper<User>wrapper=newQueryWrapper<>();wrapper.in(dbColumn,values);returnResult.success(userService.list(wrapper));}catch(IllegalArgumentExceptione){returnResult.error(e.getMessage());}}

3. 支持 @TableField 注解

@Data@TableName("t_user")publicclassUser{@TableId("user_id")privateLongid;@TableField("user_name")privateStringname;// 前端传 "name",自动映射到数据库 "user_name"@TableField("user_age")privateIntegerage;}// 前端调用GET/search?field=name&values=张三,李四// 自动转换为 SQLSELECT*FROMt_userWHEREuser_nameIN('张三','李四')

注意事项

1. 字段名安全性

  • 工具只做字段名转换,不涉及 SQL 拼接,无 SQL 注入风险
  • 建议对传入的字段名做白名单校验,或使用getDbColumnOrThrow方法

2. 异常处理建议

推荐在全局异常处理器中统一处理:IllegalArgumentException.class)

参考文档

  • MyBatis-Plus TableInfoHelper
  • MyBatis-Plus @TableField
  • MyBatis-Plus QueryWrapper

总结

DynamicFieldUtil工具类通过20 行代码解决了动态字段映射的核心问题:

一行代码:获取数据库列名
自动处理: @TableField 注解
友好提示:字段不存在时列出所有可用字段
零额外依赖:基于 MyBatis-Plus 官方 API

让你的查询条件真正实现动态化,代码更灵活、更简洁!

http://www.jsqmd.com/news/1339019/

相关文章:

  • 旗博士数字人口播智能体好用吗?适合什么人用?
  • 终极Wand-Enhancer使用指南:3分钟解锁WeMod完整功能
  • Flash擦除要等10秒?慢命令的隐藏设计
  • 如何快速配置DS4Windows:PS4手柄在Windows上的终极解决方案指南
  • 从零构建文本分析流程:Python处理非结构化数据的完整指南
  • Roaring Bitmap:亿级用户标签系统的高效存储与查询实战
  • 快捷键实战指南:从通用操作到专业软件,全面提升工作效率
  • 郑州知名背调公司,本地企业实用风控方案推荐
  • EV录屏绿色版使用技巧与性能优化指南
  • Python智能图书推荐系统开发实战
  • 华硕笔记本终极轻量控制工具:G-Helper完全指南,告别Armoury Crate卡顿烦恼
  • 细胞因子挑选指南:从实验需求到质控标准,避开选型踩坑
  • Windows Cleaner:终极免费开源系统优化工具,一键解决C盘爆红问题
  • Windows Cleaner:专治C盘爆红的免费系统优化工具
  • VHDL实现优先级仲裁器:从数字逻辑到嵌入式系统资源调度
  • 浏览器漏洞利用资源宝库:从入门到实战的完整学习路径
  • SRM软件全维度选型对比:泛微·京桥通vs五大主流采购管理软件,数智化采购最优解
  • 工厂管理效率上不去?老板必抓的5个关键,从流程到团队全打通
  • 车载信息娱乐与ADAS中的MTFC32GAZAQDW-AAT:32GB eMMC 5.1存储应用案例解析
  • 智慧水务案例|数字孪生赋能阳新滨江园区智慧供水提质升级
  • 跨越数字屏障:AO3镜像站项目的文化守护与访问革新
  • 【剪映小助手】视频信息生成接口(Video Infos)
  • 唯你秀排得系统的合规技术架构:从资金流隔离到规则引擎透明化的可验证设计
  • OBS多平台直播终极指南:obs-multi-rtmp插件高效实现一源多推
  • 中兴光猫深度管理:zteOnu工具解锁隐藏权限的3种方法
  • 2026年密室逃脱中途要提示算犯规吗
  • 2026 年现阶段广东可靠的活动板房定做厂家推荐,工地临时用房也能这么划算?原来这才是它的定做门道 - 企业推荐官-
  • 美国参议院商务委员会通过《儿童在线安全法案》,“注意义务”条款命运几何?
  • 生命涌现的小龙虾技能之【Commuter After-Work Fatigue Care (Home-Arrival Moment) | 上班族下班疲劳关怀】简介
  • 肾上腺素 (EPI):身体的应急开关,云克隆 ELISA 助力科研检测难题