0

0

使用反射动态绑定SQL查询结果到非结构体类型(如Map)

P粉602998670

P粉602998670

发布时间:2026-02-12 16:11:26

|

131人浏览过

|

来源于php中文网

原创

java反射绑定sql结果到map时字段名不匹配,需手动处理下划线转驼峰、统一key小写、用getcolumnlabel()兼容别名、避免rs.getobject(i)直接赋值,并注意jdbc驱动元数据差异。

使用反射动态绑定sql查询结果到非结构体类型(如map)

Java 反射绑定 SQL 结果到 Map 时字段名对不上

数据库列名是 user_name,但反射取 setUserName 找不到方法,直接报 NoSuchMethodException。这不是反射写错了,是默认没做下划线转驼峰的映射。

  • MyBatis 默认开启 mapUnderscoreToCamelCase=true,但那是针对实体类属性赋值,Map 没有 setter,不生效
  • ResultSetMetaData 获取列名后,得自己处理:调用 getColumnLabel()(兼容别名)而非 getColumnName()
  • 若 SQL 里写了 SELECT user_name AS userNamegetColumnLabel() 返回的就是 userName,可直接当 key 用
  • 否则就老老实实做一次下划线转驼峰:把 user_nameuserName,别依赖反射自动猜

ResultSet + 反射填充 Map<string object></string> 的安全写法

别用 rs.getObject(i) 直接塞进 Map,有些 JDBC 驱动(比如旧版 MySQL Connector/J)对 NULL 值返回 java.sql.Timestamporacle.sql.DATE,类型不统一,后续取值容易 ClassCastException

Qoder
Qoder

阿里巴巴推出的AI编程工具

下载
  • 统一用 rs.getString(i) + 类型判断兜底:对数字列先 rs.getObject(i) 再判空,非空时转 BigDecimalLong
  • Map 的 key 统一用小写字符串:meta.getColumnLabel(i).toLowerCase(),避免大小写混用导致取不到
  • 跳过自动生成的列(如 MySQL 的 ROW_NUMBER() 窗口函数结果),检查 meta.isAutoIncrement(i) 或列类型 meta.getColumnType(i) == Types.OTHER

BeanUtils.populate() 不能直接填 Map

有人试过把 ResultSet 转成 Map 后,拿 BeanUtils.populate(new HashMap(), map) 想“反向填充”,这完全走错方向——BeanUtils.populate() 是把 Map 填进 JavaBean,不是从 ResultSet 构建 Map

  • 这个方法要求 Map 的 key 必须和目标对象的 setter 方法名严格匹配(如 userNamesetUserName),对 Map 本身无意义
  • 真想动态映射,用 ResultSetMetaData 遍历列,逐个 rs.getObject(i) + meta.getColumnLabel(i) 组装 HashMap 最稳
  • Spring 的 ColumnRowMapper 或 MyBatis 的 MapWrapper 内部也是这么干的,没捷径

Oracle/PostgreSQL 的 ResultSet 列名大小写陷阱

Oracle 默认大写列名,PostgreSQL 默认小写,而 getColumnLabel() 在不同驱动下行为不一致:Oracle JDBC 驱动可能返回全大写,PG 的 pgjdbc 会按 SQL 里写的原样返回。

  • 不要假设 getColumnLabel(i) 一定是小写或驼峰,一律用 toLowerCase() 标准化 key
  • 如果 SQL 里用了双引号定义列别名(如 SELECT id AS "UserId"),getColumnLabel() 会保留大小写,这时需额外正则清洗:str.replaceAll("([A-Z])", "_$1").toLowerCase()
  • 测试时务必连真实库跑,别只用 H2 内存库——它的列名行为跟生产库差太多
事情说清了就结束。真正麻烦的不是反射本身,是 JDBC 驱动对元数据的实现差异,以及 SQL 别名、大小写、NULL 处理这些细节在不同场景下组合爆炸。

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
golang如何定义变量
golang如何定义变量

golang定义变量的方法:1、声明变量并赋予初始值“var age int =值”;2、声明变量但不赋初始值“var age int”;3、使用短变量声明“age :=值”等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

206

2024.02.23

golang有哪些数据转换方法
golang有哪些数据转换方法

golang数据转换方法:1、类型转换操作符;2、类型断言;3、字符串和数字之间的转换;4、JSON序列化和反序列化;5、使用标准库进行数据转换;6、使用第三方库进行数据转换;7、自定义数据转换函数。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

235

2024.02.23

golang常用库有哪些
golang常用库有哪些

golang常用库有:1、标准库;2、字符串处理库;3、网络库;4、加密库;5、压缩库;6、xml和json解析库;7、日期和时间库;8、数据库操作库;9、文件操作库;10、图像处理库。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

346

2024.02.23

golang和python的区别是什么
golang和python的区别是什么

golang和python的区别是:1、golang是一种编译型语言,而python是一种解释型语言;2、golang天生支持并发编程,而python对并发与并行的支持相对较弱等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

212

2024.03.05

golang是免费的吗
golang是免费的吗

golang是免费的。golang是google开发的一种静态强类型、编译型、并发型,并具有垃圾回收功能的开源编程语言,采用bsd开源协议。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

402

2024.05.21

golang结构体相关大全
golang结构体相关大全

本专题整合了golang结构体相关大全,想了解更多内容,请阅读专题下面的文章。

322

2025.06.09

golang相关判断方法
golang相关判断方法

本专题整合了golang相关判断方法,想了解更详细的相关内容,请阅读下面的文章。

197

2025.06.10

golang数组使用方法
golang数组使用方法

本专题整合了golang数组用法,想了解更多的相关内容,请阅读专题下面的文章。

784

2025.06.17

2026春节习俗大全
2026春节习俗大全

本专题整合了2026春节习俗大全,阅读专题下面的文章了解更多详细内容。

189

2026.02.11

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号