Skip to content

Mapper 数据访问 ​

本文说明 ECShopX Java 持久化层的约定:MyBatis-Plus BaseMapper、domain 表映射注解、多 Bundle 下 Mapper Bean 命名,以及与 Flyway 迁移的分工。

分层关系 ​

Controller / Service
       ↓
Repository(可选,如 ecshopx-goods)
       ↓
Mapper(extends BaseMapper<实体>)
       ↓
Domain(@MpTable / @MpField 表映射)
       ↓
MySQL
  • 结构变更(加列、改类型、索引):先改 domain → bin/make-migration → review SQL → migrate(见 数据库快速入门)
  • 数据访问:Service 经 Mapper 或 Repository 读写,Controller 不直接注入 Mapper

Domain — 表映射实体 ​

实体放在 ecshopx-<domain>/src/main/java/cn/shopex/ecshopx/<domain>/domain/。

推荐注解(本项目元数据) ​

项目扩展了 MyBatis-Plus 元数据注解,便于迁移脚本生成与文档化:

注解作用
@MpTable表名、表注释、@MpIndex 索引声明
@MpField列名、类型、长度、nullable、默认值、注释
@MpId主键列与 IdType

示例(ecshopx-goods 商品表):

java
@MpTable(value = "items", comment = "商品表", indexes = {
    @MpIndex(name = "ix_company_id", columns = {"company_id"})
})
public class Items {
    @MpId(value = "item_id", type = IdType.AUTO, columnType = "bigint", comment = "商品ID")
    private Long itemId;

    @MpField(value = "item_name", columnType = "string", length = 255, comment = "商品名称")
    private String itemName;
    // ...
}

源文件:ecshopx-goods/src/main/java/cn/shopex/ecshopx/goods/domain/Items.java

兼容注解 ​

bin/make-migration 同时识别 MyBatis-Plus 原生注解:

  • @TableName — 表名
  • @TableId — 主键
  • @TableField — 普通列

历史或简单实体可继续使用;新代码建议优先 @MpTable / @MpField,以便生成更完整的迁移 SQL 与索引元数据。

Mapper — BaseMapper ​

Mapper 接口放在 ecshopx-<domain>/.../mapper/,继承 com.baomidou.mybatisplus.core.mapper.BaseMapper<实体>,获得单表 CRUD 与 LambdaQueryWrapper 能力。

java
@Mapper
public interface ItemsMapper extends BaseMapper<Items> {
    // 模块内可声明 @Select 等自定义 SQL
}

源文件:ecshopx-goods/src/main/java/cn/shopex/ecshopx/goods/mapper/ItemsMapper.java

复杂、可复用的查询条件可封装到 repository 包(如 ItemsRepository),供 Service 注入。详见 Bundle。

多 Bundle:FqcnMapperBeanNameGenerator ​

50+ 业务模块中经常出现同名 XxxMapper 接口。默认 Spring Bean 名(如 itemsMapper)会冲突。

启动类 EcshopxApplication 在 @MapperScan 上指定 FqcnMapperBeanNameGenerator:

java
@MapperScan(
    basePackages = "cn.shopex.ecshopx.**.mapper",
    nameGenerator = FqcnMapperBeanNameGenerator.class,
    sqlSessionFactoryRef = "sqlSessionFactory",
    lazyInitialization = "true")

生成规则:将 Mapper 全限定类名中的 . 替换为 _ 作为 Bean 名,例如:

cn.shopex.ecshopx.goods.mapper.ItemsMapper → cn_shopex_ecshopx_goods_mapper_ItemsMapper

新增 Mapper 时:放在 cn.shopex.ecshopx.<domain>.mapper 包下即可,无需手工处理 Bean 名冲突。

实现类:ecshopx-common/.../mybatis/FqcnMapperBeanNameGenerator.java

读写分离 ​

架构层面支持 MySQL 读写分离与 PolarDB 等兼容实例(见 架构说明)。当前仓库未内置动态数据源路由;application.properties 仅配置单一 spring.datasource.* 数据源。

生产环境常见做法:

  • 在 JDBC URL 或中间件(PolarDB 代理、ProxySQL 等)层做读写分离
  • 或通过 Spring Boot 多数据源配置扩展(需自行引入,非本仓库默认能力)

本地开发与 Docker Compose 均使用单库连接,配置键:

配置键说明
spring.datasource.urlJDBC URL
spring.datasource.username用户名
spring.datasource.password密码

bin/make-migration 与 migrate 子命令读取同一套数据源配置(可用 --profile / --db-url 覆盖)。

禁止事项 ​

禁止说明
Controller 直接注入 Mapper经 Service 或 Repository
跨 Bundle 引用对方 Mapper通过 Port 暴露能力
手写与 Flyway 不一致的表结构结构变更走迁移并同步 domain
未 review 即执行生成的 SQL生成结果为 best-effort

相关章节 ​