跳到主要内容

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-PlusDLZ-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. 迁移顺序

  1. 在保留 MyBatis/MyBatis-Plus 的前提下引入 DLZ-DB,先验证启动和数据源。
  2. 选择一个边界清晰的实体,先保留 MP 注解,补充 CRUD 回归测试。
  3. 迁移单表查询和写操作,核对主键、null 字段、逻辑删除和唯一结果语义。
  4. 将复杂 SQL 按需放入 DB.jdbc 或预设 SQL,不以“消灭 SQL”为目标。
  5. 验证事务、批量部分失败、分页边界和多数据源。
  6. 只在旧 Mapper/XML 没有调用者且回归通过后删除;此时再决定是否统一替换实体注解。

7. 检查清单

  • 共存实体仍保留旧 Mapper 需要的 MP 注解;已完全迁移的实体明确选择并验证了 MP 兼容注解或 com.dlz.db.core.anno.*
  • IdType 与数据库主键策略一致。
  • .or/.and 没有被机械替换为错误语义。
  • 严格单条查询的多行异常已覆盖。
  • 逻辑删除字段和历史数据已对齐。
  • 事务共存和数据源切换已通过集成测试。