【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 显式映射即可解决。

相关推荐
zhangzeyuaaa7 小时前
Python 异常机制深度剖析
开发语言·python
whitelbwwww7 小时前
C++基础--类型、函数、作用域、指针、引用、文件
开发语言·c++
byzh_rc7 小时前
[AI编程从入门到入土] 配置文件
java·数据库·ai编程
leaves falling7 小时前
C/C++ const:修饰变量和指针的区别(和引用底层关系)
c语言·开发语言·c++
花千树-0107 小时前
多步骤 ReAct 实战:让 Agent 自主完成航司比价与订票
java·agent·function call·react agent·harness·j-langchain·多步骤推理
xcLeigh7 小时前
飞算 JavaAI 进阶实战:从代码生成到系统架构优化的全流程指南
java·系统架构·代码生成·java开发·飞算javaai炫技赛·javaai·飞算
比昨天多敲两行7 小时前
C++11新特性
开发语言·c++
雷工笔记7 小时前
SQL语句解析:DESC LIMIT 1
数据库·sql
xiaoye-duck7 小时前
【C++:C++11】核心特性实战:详解C++11列表初始化、右值引用与移动语义
开发语言·c++·c++11
希望永不加班8 小时前
SpringBoot 事件机制:ApplicationEvent 与监听器
java·开发语言·spring boot·后端·spring