# 错误代码分析记录 > 本文档用于记录项目开发过程中遇到的错误代码问题,包括根因分析、解决方案及经验总结,以便后续查阅和新人培训。 > > 每条记录按日期归档,最新的记录在顶部。 --- ## 记录列表 | 日期 | 标题 | 类型 | 状态 | |------------|------------------------------------------------------------|-------------------|-----| | 2026-06-04 | [@TableId 缺少 value 属性导致无效列名](#2026-06-04-tableid-缺少-value) | MyBatis-Plus 映射错误 | 已修复 | --- ## 2026-06-04:@TableId 缺少 value 属性导致无效列名 ### 问题现象 调用字典批量查询接口 `DictionaryController.getDictBatch()` 时,数据库抛出异常: ``` 无效的列名[DICTIONARY_ITEM_ID] ``` ### 根因分析 #### 相关配置 项目全局启用了 MyBatis-Plus 的下划线命名转换: ```yaml mybatis-plus: global-config: db-config: table-underline: true ``` 此配置会将 Java 字段的驼峰命名自动转为数据库下划线命名(如 `dictionaryItemId` → `dictionary_item_id`)。 #### 错误代码 **DictionaryItem.java** 中 `dictionaryItemId` 字段: ```java @TableId(type = IdType.ASSIGN_ID) // ← 没有设置 value @TableField("DictionaryItemID") private String dictionaryItemId; ``` **Dictionary.java** 中 `dictionaryCode` 字段: ```java @TableId // ← 没有设置 value @TableField("DictionaryCode") private String dictionaryCode; ``` `@TableId` 没有设置 `value` 属性时,MyBatis-Plus 会走默认命名策略来确定主键列名。在 `table-underline: true` 的作用下, `dictionaryItemId` 被转换为 `dictionary_item_id`,`dictionaryCode` 被转换为 `dictionary_code`。 而 `@TableId` 对主键列的优先级高于 `@TableField`,所以 `@TableField("DictionaryItemID")` 并未生效,导致生成的 SQL 中主键列名为 `dictionary_item_id`(即错误信息中的 `DICTIONARY_ITEM_ID`),与实际数据库列名 `DictionaryItemID` 不匹配。 #### 为何 SppbVideo 没有此问题 `SppbVideo.java` 的字段名(如 `createBy`、`updateTime`)通过 `table-underline: true` 转换后恰好对应数据库的下划线列名( `create_by`、`update_time`),且 `@TableId` 的字段名为 `id`,转换后为 `id`,与数据库一致,因此不需要 `@TableField`。 ### 解决方案 #### 修复思路 在 `@TableId` 中显式指定 `value` 属性,使其匹配实际数据库列名,同时删除该字段上冗余的 `@TableField` 注解。 #### 修改内容 **修改文件 1:** `jeecg-boot/jeecg-boot-module/jeecg-module-zjrs/src/main/java/org/jeecg/modules/zjrs/dictionary/entity/DictionaryItem.java` - 改动:`dictionaryItemId` 字段的 `@TableId(type = IdType.ASSIGN_ID)` → `@TableId(value = "DictionaryItemID", type = IdType.ASSIGN_ID)` - 删除:该字段上冗余的 `@TableField("DictionaryItemID")` **修改文件 2:** `jeecg-boot/jeecg-boot-module/jeecg-module-zjrs/src/main/java/org/jeecg/modules/zjrs/dictionary/entity/Dictionary.java` - 改动:`dictionaryCode` 字段的 `@TableId` → `@TableId(value = "DictionaryCode")` - 删除:该字段上冗余的 `@TableField("DictionaryCode")` #### 涉及文件清单 | 文件 | 操作 | 原因 | |-----------------------------------------------------------------------------------------------------------------------------|----|---------------------------------------------------------------| | `jeecg-boot/jeecg-boot-module/jeecg-module-zjrs/src/main/java/org/jeecg/modules/zjrs/dictionary/entity/DictionaryItem.java` | 修改 | `@TableId` 补充 `value = "DictionaryItemID"`,删除冗余 `@TableField` | | `jeecg-boot/jeecg-boot-module/jeecg-module-zjrs/src/main/java/org/jeecg/modules/zjrs/dictionary/entity/Dictionary.java` | 修改 | `@TableId` 补充 `value = "DictionaryCode"`,删除冗余 `@TableField` | ### 经验总结 #### @TableId 使用规范 - 当数据库主键列名与 Java 字段名的默认下划线转换结果不一致时,**必须在 `@TableId` 中显式设置 `value`** 属性 - `@TableId` 的 `value` 优先级高于 `@TableField`,也高于全局 `table-underline` 配置 - `@TableId` 已包含字段映射功能,同一字段上无需再加 `@TableField` #### @TableField 使用时机 以下情况需要加 `@TableField`: - 数据库列名不遵循驼峰转下划线的默认命名规则(如 PascalCase 风格) - 字段在数据库中不存在,需要 `@TableField(exist = false)` 排除 - 需要指定字段更新策略等额外配置 以下情况不需要加 `@TableField`: - 数据库列名与默认命名转换结果一致(`createBy` → `create_by`) - 主键字段上已有带 `value` 属性的 `@TableId`