使用MyBatis操作PostgreSQL时如何处理保留关键字字段
问题描述
在PostgreSQL 13中创建name、password这类属于保留关键字的字段时,MyBatis自动生成的SQL会默认用反引号包裹保留字字段,示例如下:
INSERT INTO apple_server_notification_record (created_time, updated_time, notification_type, auto_renew_product_id, auto_renew_status, auto_renew_status_change_date, auto_renew_status_change_date_ms, auto_renew_status_change_date_pst, environment, `password`, bid, bvrs) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
在PostgreSQL 13中执行该SQL会抛出语法错误,提示反引号位置语法异常。
已知修改数据库字段password为apple_auth_password可解决问题,但实体类中定义的属性为private String password;,修改字段名需要额外调整苹果服务回调请求的字段映射逻辑,想要更优的解决方案。
问题根源
报错本质是不同数据库对保留关键字的转义符规范不兼容:
- MySQL类数据库使用反引号
`作为保留字转义符 - PostgreSQL遵循SQL标准,使用双引号
"作为保留字转义符
MyBatis默认按MySQL规则给识别到的保留字字段加反引号,放到PostgreSQL中执行就会触发语法错误。
推荐解决方案(按优先度排序)
方案1:全局配置MyBatis的转义符适配PostgreSQL(无侵入,推荐)
直接修改MyBatis全局配置,让自动生成SQL时用双引号作为转义符,不需要修改任何实体类、Mapper代码,完全不影响苹果回调的参数映射逻辑。
如果是SpringBoot项目,在application.yml中添加配置:
mybatis: configuration: # 开启自动给关键字加转义符 auto-delimit-keywords: true # 配置转义起始符为双引号 beginning-delimiter: "\"" # 配置转义结束符为双引号 ending-delimiter: "\""
如果使用MyBatis-Plus,额外增加数据库类型配置即可自动适配转义符:
mybatis-plus: configuration: db-type: postgresql
方案2:单独给保留字字段指定转义后的列名
如果不想修改全局配置,可以单独给有冲突的实体类字段加注解指定列名,实体类属性名保持password不变:
如果用的是MyBatis-Plus,给字段加@TableField注解:
@TableField("\"password\"") private String password;
如果用的是JPA或者通用Mapper,加@Column注解:
@Column(name = "\"password\"") private String password;
如果是手写Mapper XML,直接把字段部分的反引号改成双引号即可:
<insert id="insertSelective" parameterType="xxx.AppleServerNotificationRecord"> INSERT INTO apple_server_notification_record ( -- 其他字段省略 "password", -- 其他字段省略 ) VALUES ( -- 占位符省略 ) </insert>
方案3:修改PostgreSQL的配置兼容反引号(不推荐)
可以修改PostgreSQL的sql_mode参数开启反引号支持,但属于非标准配置,后续迁移数据库容易出问题,不建议使用。
内容的提问来源于stack exchange,提问作者Dolphin
相关产品推荐
相关产品推荐

