You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2.4 KiB
2.4 KiB
JPA/Hibernate 命名策略:孤立单大写字母陷阱
Spring Boot 默认的 SpringPhysicalNamingStrategy 把驼峰转蛇形时,会把"孤立的单个大写字母"当成缩略语(同 URL / ID 处理),不插下划线。触发条件:某个大写字母的左侧是小写或字符串开头、右侧是大写或字符串结尾。
这会导致 Hibernate 建表的物理列名与 MyBatis-Plus 生成 SQL 时的列名(走 camelToUnderscore)不一致,报错形如:
java.sql.SQLSyntaxErrorException: Unknown column 'party_a_clear' in 'field list'
已知踩坑记录:
| Java 字段 | 期望列名 | Hibernate 实际建成 | MyBatis SQL 写的 |
|---|---|---|---|
partyA |
party_a |
partya ❌ |
party_a |
partyAClear |
party_a_clear |
partyaclear ❌ |
party_a_clear |
规则:Java 字段名里出现下述形态的孤立单大写字母时,必须在 @Column 上显式写 name="蛇形列名" 钉死:
- 结尾单大写:
xxxA、xxxB、xxxZ - 夹在小写与大写词之间的单大写:
xxxAYyy、xxxBClear - 连续单大写:
xxxABC(会整段当缩略语,不断词)
反例(这些形态不会踩坑,无需 @Column(name=...)):
ownerUserId→owner_user_id✅(Id是两字符段,按普通词处理)bidForm→bid_form✅(Form是完整词)provinceCode→province_code✅
修复模板:
@Column(name = "party_a_clear", columnDefinition = "tinyint not null default 0 comment '甲方是否明确'")
private Integer partyAClear = 0;
为什么不换命名策略:换策略会影响全部已建对的列(几十列),代价远大于给个位数问题字段加 @Column(name=...)。
为什么线上很久才暴露:ddl-auto: update 只加列不改列。老字段可能长期只走 SELECT(ResultMap 兜住)不写入,直到某天走 INSERT/UPDATE 才炸。新加 Java 字段时如果撞规则,第一次持久化就会报 Unknown column。
新增字段检查清单(写完 entity、跑起来之前):
- 字段名里有没有孤立单大写字母?没有 → 直接过。
- 有 → 加
@Column(name = "snake_case_name", columnDefinition = "...")。 ddl-auto: update环境下,如果表已经存在且字段名撞过坑,需要一条ALTER TABLE t CHANGE 旧列名 新列名 类型 ...;手工迁移,Hibernate 不会自动改名。