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.
46 lines
2.4 KiB
46 lines
2.4 KiB
|
4 days ago
|
### 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` ✅
|
||
|
|
|
||
|
|
**修复模板**:
|
||
|
|
|
||
|
|
```java
|
||
|
|
@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、跑起来之前):
|
||
|
|
|
||
|
|
1. 字段名里有没有孤立单大写字母?没有 → 直接过。
|
||
|
|
2. 有 → 加 `@Column(name = "snake_case_name", columnDefinition = "...")`。
|
||
|
|
3. `ddl-auto: update` 环境下,如果表已经存在且字段名撞过坑,需要一条 `ALTER TABLE t CHANGE 旧列名 新列名 类型 ...;` 手工迁移,Hibernate 不会自动改名。
|