问题描述: 基于 MyBatis-Plus 开发的 Spring Boot 项目中,如何在改动项目代码最少的前提下,更新数据库表中的字段,完成项目的更新上线。
为了在变动较少代码的前提下完成数据库字段名的更新(如将 id 改为 业务_id),同时使用 MyBatis-Plus 的 ORM 功能,可以按照以下步骤操作。核心思路是通过注解和配置映射新旧字段,避免大规模修改业务代码。
解决方案步骤:
1. 步骤1:修改数据库表结构
使用 SQL 脚本直接修改表字段名:
ALTER TABLE your_table RENAME COLUMN id TO 业务_id;
注意:需确保所有相关表都执行修改(如关联表的外键字段)。
2. 步骤2:修改实体类字段映射
在实体类中使用 @TableId 和 @TableField 注解绑定新字段名:
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableField;
public class YourEntity {
// 映射主键字段
@TableId(value = "业务_id") // 指定数据库字段名
private Long id; // 保持属性名不变,减少代码改动
// 示例:其他字段修改
@TableField("新字段名")
private String oldFieldName;
}
关键点:
- 实体类属性名(如
id)保持不变,仅通过注解映射到新字段名业务_id。 - MyBatis-Plus 的 CRUD 操作将自动使用新字段名。
3. 步骤3:处理自定义 SQL 或 XML 文件(推荐优先使用)
仅通过设置别名的方式修改SQL语句,不修改<resultMap></resultMap>中的内容,经过试验没问题。
试验方式将user表中的id修改为user_id,email修改为emailorQQ。
如果项目中有手写 SQL(如 Mapper XML 文件),需全局替换字段名:
<!-- 修改前 -->
<select id="selectById" resultType="YourEntity">
SELECT id, name FROM your_table WHERE id = #{id}
</select>
<!-- 修改后 -->
<select id="selectById" resultType="YourEntity">
SELECT 业务_id AS id, name FROM your_table WHERE 业务_id = #{id}
</select>
技巧:
- 使用
AS保持结果集映射到实体类的属性名(如业务_id AS id)。 - 用 IDE 的全局替换功能批量修改 XML 中的字段名。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.todo.dao.IUserDao">
<resultMap id="dataMap" type="com.example.todo.entity.User">
<id column="id" property="id"/>
<result column="username" property="username"/>
<result column="password" property="password"/>
<result column="nick_name" property="nickName"/>
<result column="email" property="email"/>
<result column="phone_number" property="phoneNumber"/>
<result column="avatar" property="avatar"/>
<result column="signature" property="signature"/>
<result column="deleted" property="deleted"/>
<result column="create_time" property="createTime"/>
<result column="update_time" property="updateTime"/>
</resultMap>
<select id="getUserByIdAndUserName" resultMap="dataMap">
select user_id as id, username, password, nick_name, emailorQQ as email
from user
where user_id=#{id} and username=#{userName}
limit 10
</select>
</mapper>
注意事项: <select></select>中的SQL语句是直接发送给MySQL的,随后将MySQL查询出的结果再进行<resultMap></resultMap>到实体类的映射。
4. 修改xml注意事项(选择步骤3可跳过步骤4)
同时修改resultMap与SQL语句,经过试验没问题。
进修改SQL语句中的字段,运行查询会没问题,但是查询出的已修改字段为null。
需要同时修改xml文件中的<resultMap></resultMap>内容与SQL语句中的内容。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.todo.dao.IUserDao">
<resultMap id="dataMap" type="com.example.todo.entity.User">
<id column="user_id" property="id"/>
<result column="username" property="username"/>
<result column="password" property="password"/>
<result column="nick_name" property="nickName"/>
<result column="emailorQQ" property="email"/>
<result column="phone_number" property="phoneNumber"/>
<result column="avatar" property="avatar"/>
<result column="signature" property="signature"/>
<result column="deleted" property="deleted"/>
<result column="create_time" property="createTime"/>
<result column="update_time" property="updateTime"/>
</resultMap>
<select id="getUserByIdAndUserName" resultMap="dataMap">
select user_id, username, password, nick_name, emailorQQ
from user
where user_id=#{id} and username=#{userName}
limit 10
</select>
</mapper>
5. 步骤4:检查全局配置下划线转换(可选)
若多数字段遵循 驼峰转下划线 规则,在 application.yml 中配置:
mybatis-plus:
configuration:
map-underscore-to-camel-case: true # 开启自动转换
global-config:
db-config:
column-format: "%s" # 防止MP自动添加反引号(可选)
此配置可使 业务_id 自动映射到实体类属性 业务Id(需同步改属性名)。
慎用:如果仅部分字段改名,建议优先用注解。
6. 步骤5:统一处理条件构造器(核心)
MyBatis-Plus 的 QueryWrapper 或 LambdaQueryWrapper 依赖实体类注解,无需修改:
// 修改前
queryWrapper.eq("id", 1);
// 修改后:直接使用Lambda表达式,避免硬编码字段名!
queryWrapper.eq(YourEntity::getId, 1);
重要:
- 禁止硬编码字段名(如
eq("id", 1)),改用 Lambda 表达式(YourEntity::getId)。 - Lambda 构造器会自动读取注解映射的字段名(
业务_id)。
7. 修复外键关联和业务代码
- 关联查询:在
@TableField注解中指定外键字段:
@TableField(value = "关联业务_id")
private Long refId;
- 业务代码:如果存在直接使用字段名的场景(如反射、Map 操作),需局部调整。
8. 测试与回归验证
- 单元测试:重点测试增删改查和复杂查询。
- 集成测试:验证关联操作和事务。
- 日志检查:开启 MyBatis SQL 日志,确认生成的 SQL 使用新字段名:
logging:
level:
com.your.mapper: debug
总结优化点:
| 措施 | 目的 |
|---|---|
| 保持实体类属性名不变 | 减少业务代码、Service、Controller 层的改动 |
| 注解驱动映射 | 通过 @TableId/@TableField 绑定新字段名,解耦数据库与代码 |
| Lambda 条件构造器 | 避免硬编码字段名,依赖注解自动映射 |
| 全局替换 XML 字段名 | 快速修复自定义 SQL |
| 渐进式修改 | 按模块逐步验证,降低风险 |
通过以上步骤,90% 的改动集中在 实体类注解 和 XML/SQL 文件,业务逻辑层几乎无需修改,最小化变更影响。
本文内容存在AI生成,但文中提到的方法已通过试验验证。如文中存在错误描述,还请各位大佬批评指正!