【Java】关于控制台 SQL 日志显示查询有值但Swagger不显示字段问题

场景:做"操作日志 -> 获取操作人列表(姓名+职位)"接口时,控制台 MyBatis 日志能看到 position_name 有值,但 Swagger 响应 JSON 里只有 id/name,职位字段不见了。


1. 背景需求

操作日志页面有一个"操作人"筛选框/弹窗,需要后端提供一个人员列表接口,每条数据包含:

涉及三张表的逻辑外键关系:

  • staff.idstaff_orginfo.staff_id
  • position.idstaff_orginfo.position_id

并且列表要按创建时间倒序(最新的在上)。

对应后端接口(示例):

  • GET /sys/optlog/operators?pageIndex=1&pageSize=10&name=管理员

2. 问题现象(非常迷惑)

调用接口后:

  • 控制台 SQL 日志显示查询列里有 position_name,并且每行数据里职位也有值。
  • 但 Swagger 的响应 JSON 里 rows 只包含 idname,没有 position_name

也就是说:SQL 有值,但接口响应不展示该字段


3. 定位"问题在哪一层"

  1. SQL 层:数据库是否真的能查到字段?
  2. ORM 映射层:MyBatis 是否把列正确映射到 DTO 属性?
  3. JSON 序列化/Swagger 展示层:DTO 属性是否被序列化输出?

这次排查非常关键的一点是:

  • 控制台既然能打印出 Columns: id, name, position_name,并且 Row 里职位也有值
    → 说明 SQL 层没问题
  • Swagger 响应里却没有职位字段
    → 极大概率是 ORM 映射层序列化层 的问题。

4. 关键线索:MyBatis 下划线转驼峰映射

MyBatis(或 MyBatis-Plus)经常会开启一个全局配置:

  • mapUnderscoreToCamelCase=true

开启后,MyBatis 会把数据库列名自动做转换:

  • position_namepositionName
  • add_timeaddTime

这就带来一个"坑":

如果 DTO 里字段写成了下划线风格:

java 复制代码
private String position_name;

而 SQL 返回的列名是 position_name,MyBatis 会尝试去找 positionName 来赋值,结果找不到,字段就一直是 null

一旦 DTO 字段为 null,再结合项目常见的 JSON 序列化配置(不输出 null 字段),Swagger 里就会表现为:

"返回里根本没有这个字段"

这也是为什么明明 SQL 有值,Swagger 却像"没返回职位"。


5. 最终解决方案(两种任选其一)

方案 A(最简单):DTO 属性改成驼峰

把 DTO 的职位字段改为 positionName

java 复制代码
public class OptlogOperatorDTO {
    private Long id;
    private String name;
    private String positionName;
}

然后 SQL 仍然用别名 position_name

sql 复制代码
SELECT p.name AS position_name

这样 MyBatis 会自动把 position_name 映射到 positionName,字段就能正常出现在 Swagger 响应里。

你这次最终采用的就是这个方案,修改后立刻生效。

方案 B(更稳健):XML 显式 resultMap 强制映射

如果你希望 DTO 里依然用下划线字段名(不推荐,但有时前端字段历史包袱很大),可以在 mapper.xmlresultMap

xml 复制代码
<resultMap id="OptlogOperatorDTOMap" type="com.xxx.OptlogOperatorDTO">
  <id column="id" property="id"/>
  <result column="name" property="name"/>
  <result column="position_name" property="position_name"/>
</resultMap>

<select id="selectOptlogOperators" resultMap="OptlogOperatorDTOMap">
  SELECT s.id, s.name, p.name AS position_name
  ...
</select>

这样映射行为就不依赖全局配置,最稳定。


总结

这次问题之所以"看起来像 SQL/联表错了",是因为:

  • SQL 的确查到了数据(控制台日志有值)
  • 但 MyBatis 映射层因为 下划线转驼峰 的规则,把 position_name 试图映射到 positionName
  • DTO 字段名若写成 position_name,就会映射失败,字段变 null

最终通过统一 DTO 命名(positionName)或 resultMap 显式映射即可解决。

相关推荐
酉鬼女又兒2 小时前
零基础入门前端JavaScript Object 对象完全指南:从基础到进阶(可用于备赛蓝桥杯Web应用开发赛道)
开发语言·前端·javascript·职场和发展·蓝桥杯
R-sz2 小时前
坐标转换踩坑实录:UTM → WGS84 → GCJ02 前端后端一致实现
开发语言·前端·python
凤山老林2 小时前
深度解析Skill机制:如何通过Spring AI + 阿里巴巴对接任意大模型实现智能技能调用?
java·人工智能·ai agent·skill·spring ai
Clownorange2 小时前
maven下载安装配置教程
java·maven
不染尘.2 小时前
拓扑排序算法
开发语言·数据结构·c++·算法·排序算法·广度优先·深度优先遍历
m0_518019482 小时前
高性能日志库C++实现
开发语言·c++·算法
UnicornDev2 小时前
从零开始的C++编程之旅——第六篇:数组与字符串——批量数据的存储与处理
java·开发语言·算法
小陈工2 小时前
2026年3月23日技术资讯洞察:AI Agent失控,Claude Code引领AI编程新趋势
开发语言·数据库·人工智能·后端·python·性能优化·ai编程
liulilittle2 小时前
LINUX RING BUFFER TUN/TAP 2
linux·运维·服务器·开发语言·网络·c++