MySQL不支持DDD,但可通过表结构设计、约束和命名规范适配DDD原则:聚合根建主表并用外键/检查约束保障内聚性,值对象嵌入JSON或冗余字段,禁止跨聚合外键引用,用视图封装只读查询,领域逻辑优先放在应用层事务中实现。

MySQL 本身不支持 DDD,但可以配合 DDD 建模原则使用
MySQL 是关系型数据库,没有内置聚合根、值对象、领域事件等概念,也不提供领域模型校验或生命周期管理。DDD 是一种设计思想,不是数据库能力。关键在于:如何让 MySQL 的表结构、约束和访问方式,不破坏 DDD 的边界与语义。
用表映射聚合根,而非实体或值对象
聚合根是 DDD 中唯一允许被外部直接引用的领域对象。对应到 MySQL,应为每个聚合根建一张主表,并通过外键、唯一约束、CHECK(MySQL 8.0.16+)体现其内聚性。
-
order表作为Order聚合根,包含id、status、created_at等核心字段;订单项(OrderItem)必须通过order_id关联,且不允许独立存在(加ON DELETE CASCADE) - 避免把
Address(值对象)单独建address表并全局复用——它应作为 JSON 字段嵌入order或customer表(shipping_address JSON),或冗余为若干字段(ship_street,ship_city),前提是该地址不承载独立业务规则 - 禁止跨聚合根直接外键引用:比如
product_id在order_item表中应为普通字段(非外键),因为Product是另一个聚合根,引用应通过领域服务协调,而非数据库级强制
用视图 + 存储过程封装领域行为(谨慎使用)
MySQL 可以用 VIEW 暴露只读聚合快照,用 PROCEDURE 封装需事务保证的复合操作(如“创建订单并扣减库存”),但要注意:存储过程会把领域逻辑下推到数据库层,削弱可测试性与语言一致性。
- 适合场景:报表类聚合查询(
CREATE VIEW order_summary AS SELECT ...)、强一致性要求且性能敏感的原子操作 - 风险点:MySQL 存储过程难调试、难版本化、无法 mock,与应用层 ORM(如 SQLAlchemy、MyBatis)协同成本高
- 更推荐做法:在应用层用事务包裹多个
INSERT/UPDATE,由领域服务控制流程,MySQL 仅提供 ACID 底层保障
用命名与注释显式表达领域语义
MySQL 不识别领域术语,但字段名、表名、索引名、COMMENT 都是传达意图的载体。这对团队理解边界至关重要。
- 表名用单数、领域术语:
order而非orders;inventory_adjustment而非stock_log - 字段加 COMMENT 说明业务含义:
ALTER TABLE `order` MODIFY `status` ENUM('draft', 'confirmed', 'shipped', 'cancelled') COMMENT '订单生命周期状态,变更需经领域规则校验'; - 索引名带业务前缀:
idx_order_customer_id明确这是支撑“按客户查订单”的查询场景,而非技术索引 - 避免通用字段名:
type、flag、data会模糊领域职责,改用payment_method、is_tax_included、metadata_json











