
Spring Data JDBC 默认生成的 SQL 语句会直接使用实体属性名作为列别名,当属性名为 SQL 保留关键字(如 order)时,会导致语法错误或映射失败;需通过适配数据库方言的引号方式(如反引号、方括号)显式转义列名,并确保别名与属性名一致以完成正确映射。
spring data jdbc 默认生成的 sql 语句会直接使用实体属性名作为列别名,当属性名为 sql 保留关键字(如 `order`)时,会导致语法错误或映射失败;需通过适配数据库方言的引号方式(如反引号、方括号)显式转义列名,并确保别名与属性名一致以完成正确映射。
在 Spring Data JDBC 中,实体属性名若与数据库保留关键字(如 order、group、user 等)冲突,框架在生成 SELECT 查询时会直接将该属性名用作列别名(例如 AS order),从而触发数据库语法错误(如 SQL Server 报错 Incorrect syntax near the keyword 'order')。更隐蔽的问题是:即使通过 @Column("\"ORDER\"") 强制加引号,JDBC 驱动返回的 ResultSet 列名仍为带引号的 "ORDER",而 Spring Data JDBC 的默认映射器会按未加引号的属性名(order)去匹配列,导致值无法绑定,最终该字段始终为默认值(如 int 类型为 0)。
✅ 正确解决方案是:使用符合目标数据库方言的标识符引号,且确保 @Column 值与实际列名完全一致,同时避免在别名中引入额外引号干扰映射。
不同数据库的推荐写法如下:
-
MySQL / H2 / PostgreSQL(兼容模式):使用反引号(backtick)
@Table("TEST_TABLE") @Data public class TestTableEntity { @Id private int id; @Column("`order`") // ✅ 反引号包裹,SQL 中解析为 `order` private int order; } -
SQL Server:使用方括号(bracket)
@Column("[order]") // ✅ 方括号包裹,SQL 中解析为 [order] private int order; PostgreSQL(原生模式):使用双引号(double quote)——但需注意:必须保证 @Column 值与 ResultSet.getMetaData().getColumnName(i) 返回的列名严格一致。此时应配合自定义 ResultSetExtractor 或启用 spring.data.jdbc.queries.column-mapping-enabled=true(Spring Data JDBC 3.2+),但更稳妥的方式仍是优先选用方括号(SQL Server)或反引号(MySQL/H2)。
⚠️ 注意事项:
- 不要混用引号风格(如 @Column("\"order\"") 在 SQL Server 中无效,且会导致列名不匹配);
- NamingStrategy 自定义仅影响自动推导的列名,对显式声明的 @Column 无效,因此重写 getColumnName() 无法修复本例问题;
- 若使用 Lombok 的 @Data,请确认 order 字段的 getter/setter 已生成(Lombok 默认支持,无需额外配置);
- 建议在 application.yml 中开启 SQL 日志以便验证最终执行语句:
logging: level: org.springframework.data.jdbc.core: DEBUG org.springframework.jdbc.core: DEBUG
总结:Spring Data JDBC 的列映射依赖于 ResultSet 中的列名与实体属性名(或 @Column 指定名)的精确匹配。面对保留关键字,应选择数据库原生支持的标识符分隔符,并确保 @Column 值既是合法 SQL 标识符,又能被 JDBC 驱动如实暴露为元数据列名——反引号(MySQL/H2)和方括号(SQL Server)是最可靠、最广泛兼容的方案。











