7.1 从 MyBatis / MyBatis-Plus 迁移
迁移建议采用渐进式:先让 DLZ-DB 与现有 Mapper 共存,从可回归的单表 CRUD 开始,再处理复杂 SQL 和事务边界。是否减少代码或提升启动速度取决于实际项目,本页不做固定百分比或倍数承诺。
开始改代码前先阅读 公共 API;让 AI 执行迁移时,再提供 AI 迁移任务指南。
1. 引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>top.dlzio</groupId>
<artifactId>dlz-db-spring-boot-starter</artifactId>
<version>8.0.0</version>
</dependency>
Starter 使用 Spring 容器中的 DataSource 自动初始化。不需要额外编写 DlzDbConfigs 或继承 DLZ-DB 配置类。spring-boot-starter-jdbc 在 DLZ-DB Starter 中是 provided,若现有应用尚未直接依赖它,需要显式加入。共存期间应确认 MyBatis 和 DLZ-DB 使用同一个预期 DataSource。
2. 实体注解
共存阶段不要先替换仍被旧 Mapper 使用的 MyBatis-Plus 注解。DLZ-DB 8.0 会通过反射识别 MP 常用的 @TableName、@TableField、@TableId 及主键策略,可先保留原实体完成一小段 CRUD 迁移。该兼容只覆盖源码明确映射的表、字段和主键元数据,不代表 MP 注解的全部属性和插件行为都生效。
当某个实体的旧 Mapper 已下线后,可选择继续保留已验证的兼容注解,也可统一替换为 DLZ-DB 注解:
import com.dlz.db.core.anno.IdType;
import com.dlz.db.core.anno.TableField;
import com.dlz.db.core.anno.TableId;
import com.dlz.db.core.anno.TableName;
@TableName("sys_user")
public class User {
@TableId(type = IdType.AUTO)
private Long id;
@TableField("user_name")
private String name;
private Integer deleted;
}
核对要点:
@TableId默认为IdType.SEQ;数据库自增必须显式使用IdType.AUTO。- DLZ-DB
@TableField当前属性为value/exist/select/comment,不应直接复制 MP 的其他属性。 - 逻辑删除基于配置的字段名(默认
deleted),不依赖 MP@TableLogic。 - MP 自动填充、乐观锁、租户和类型处理器等能力不在这组注解兼容映射内,必须单独迁移和验证。
3. CRUD 对照
| MyBatis-Plus | DLZ-DB 8.0 |
|---|---|
userMapper.selectById(id) | DB.pojo.selectById(User.class, id) |
userMapper.selectList(wrapper) | DB.pojo.selectWrapper(User.class).eq(...).queryBeanList() |
userMapper.selectPage(page, wrapper) | DB.pojo.selectWrapper(User.class).eq(...).page(1, 10).queryBeanPage() |
userMapper.insert(user) | DB.pojo.insert(user) |
userMapper.updateById(user) | DB.pojo.updateById(user) |
userMapper.deleteById(id) | DB.pojo.deleteById(User.class, id) |
复合条件要特别处理:DLZ-DB 使用 .ands(...) 和 .ors(...),且 .ors(...) 表示 lambda 内部 OR,语义不要按 MyBatis-Plus 同名 API 直接替换。
4. 复杂 SQL
- 一次性 SQL:
DB.jdbc,使用?占位符。 - 集中管理的 SQL:
DB.sql,使用#{key}命名参数。 - Wrapper 主要处理单表;JOIN、CTE、UNION、窗口函数和复杂聚合不要强行转成 Wrapper。
List<User> users = DB.jdbc.list(
"SELECT * FROM user WHERE status = ?", User.class, 1);
List<User> preset = DB.sql.list(
"key.user.findActive", User.class, new JSONMap("status", 1));
5. 事务与共存
- Spring 中可以继续使用
@Transactional。 - 框架无关的代码可使用
DB.tx.run(...)。 DB.ds.use(...)只切换数据源,不开启事务。- 同一业务事务中混用 MyBatis 和 DLZ-DB 前,必须以集成测试确认两者获取的是同一个 Spring 事务连接。
6. 迁移顺序
- 在保留 MyBatis/MyBatis-Plus 的前提下引入 DLZ-DB,先验证启动和数据源。
- 选择一个边界清晰的实体,先保留 MP 注解,补充 CRUD 回归测试。
- 迁移单表查询和写操作,核对主键、null 字段、逻辑删除和唯一结果语义。
- 将复杂 SQL 按需放入
DB.jdbc或预设 SQL,不以“消灭 SQL”为目标。 - 验证事务、批量部分失败、分页边界和多数据源。
- 只在旧 Mapper/XML 没有调用者且回归通过后删除;此时再决定是否统一替换实体注解。
7. 检查清单
- 共存实体仍保留旧 Mapper 需要的 MP 注解;已完全迁移的实体明确选择并验证了 MP 兼容注解或
com.dlz.db.core.anno.*。 -
IdType与数据库主键策略一致。 -
.or/.and没有被机械替换为错误语义。 - 严格单条查询的多行异常已覆盖。
- 逻辑删除字段和历史数据已对齐。
- 事务共存和数据源切换已通过集成测试。