Spring Boot R2DBC使用@Query做INNER JOIN部分字段返回null问题
问题原因及解决方案
核心原因
Spring Data R2DBC 默认启用驼峰属性名转蛇形下划线列名的映射规则,会将POJO的驼峰属性名自动转换为下划线格式后,再和SQL查询返回的结果集列名做匹配:
- 比如POJO属性
inboundID会被转换为inbound_id去匹配结果集列,而你SQL返回的列名为inboundID,二者不匹配因此返回null - 你示例中能正常返回的
MSISDN(全大写无小写驼峰分段)、message(全小写无大写分段)刚好符合转换后的匹配规则,所以能正常映射到值
验证方法
你可以临时修改SQL给所有列加下划线格式的别名,测试是否能正常返回所有字段值:
@Query("SELECT" + " i.inboundID AS inbound_id, " + " i.MSISDN," + " i.message," + " ms.shortDesc AS short_desc," + " i.modifiedByUsername AS modified_by_username" + " FROM inbound i " + " JOIN messageStatuses ms on ms.statusCode = i.inboundStatus " + " JOIN conversation cm on i.conversationID = cm.conversationID " + " LIMIT :limit OFFSET :offset ")
如果修改后所有字段都能正常返回,即可确认是映射规则导致的问题。
解决方案
提供两种可选方案:
方案1:全局关闭驼峰转下划线映射
在application.yml/application.properties中添加配置,让R2DBC直接用POJO属性名和结果集列名精确匹配:
spring: data: r2dbc: convert: camel-case-to-snake-case: false
该方案适合项目中所有表列名都和POJO属性名保持一致的场景。
方案2:给POJO属性手动指定列名
不需要修改全局配置,给需要映射的属性添加@Column注解显式指定对应的列名即可:
public class MessageModel { @Column("inboundID") private Integer inboundID; private String MSISDN; private String message; @Column("shortDesc") private String shortDesc; ... @Column("modifiedByUsername") private String modifiedByUsername; }
该方案适合只有部分表需要自定义映射的场景。
其他排查点
如果上述方案无效,可以检查两个点:
- POJO是否提供了public的无参构造函数,R2DBC需要依赖无参构造实例化映射对象
- 多表JOIN的查询结果是否存在重名列,如果有重名需要给列加别名避免映射冲突
内容的提问来源于stack exchange,提问作者Peter
相关产品推荐
相关产品推荐

