1.MVC与DDD数据相关
最本质的区别所在:依赖倒置和领域模型的纯净性。
1. MVC 做对比
在传统的 MVC 三层架构 中,流程通常是这样的:
-
Controller: 接待员,接收请求。
-
Service: 业务员,写业务逻辑。
-
Mapper/DAO: 仓库管理员,直接操作数据库。
路径:
Controller→Service→Mapper(DAO)→DB
MVC 的问题:
Service 层直接依赖 Mapper,意味着业务逻辑直接依赖了数据库表结构。如果数据库表改了,POJO(持久化对象)就得改,Service 里的 get/set 可能也得跟着改。业务逻辑被数据库“绑架”了。
2. DDD 架构下的“三方会谈”
在 DDD(你截图中的架构)中,为了让业务逻辑(Domain)不受数据库影响,引入了 Repository(仓储) 的概念,并把 Mapper/DAO 降级了。
我们来看你截图中的三个角色,它们的分工非常明确:
第一角色:IActivityRepository (接口)
-
位置: 在
domain包(或其子包)里。 -
身份: 业务部门提出的“需求合同”。
-
作用: 领域层(Domain)是大老板,它只规定:“我要根据 ID 查一个活动信息,我不管你去哪里查(MySQL、Redis、还是 Excel),反正你要给我返回一个标准的 领域实体(Entity)。”
-
注意: 这里的方法返回值通常是
ActivityEntity(领域对象),而不是数据库对应的ActivityPO(数据库表映射对象)。
第二角色:DAO (IRaffleActivityDao)
-
位置: 在
infrastructure(基础设置层) →dao包里。 -
身份: 干脏活累活的“数据库操作员”。
-
作用: 它就是你熟悉的 Mapper。它只懂 SQL,只懂数据库表结构。它返回的是
PO(Persistent Object) 或者DO(Data Object),也就是和数据库表 1:1 对应的对象。
第三角色:Repository Impl (ActivityRepository)
-
位置: 在
infrastructure→repository包里。 -
身份: 适配器 / 转换器。
-
作用: 它是最关键的“胶水”。
-
它实现了 Domain 层的
IActivityRepository接口(履行合同)。 -
它注入了
IRaffleActivityDao(使用工具)。 -
核心逻辑: 当 Domain 调用它时,它先指挥 DAO 去数据库查出
PO数据,然后把PO转换(Convert) 成Entity,最后返回给 Domain。
-
3. 为什么要搞这么复杂?(核心价值)
你可能会问:直接用 DAO 不行吗?为什么要中间加一层 Repository?
原因有二:
-
依赖倒置(解耦):
-
在 DDD 中,Domain 层(核心业务)不依赖 Infrastructure 层(数据库实现)。
-
Domain 层定义接口(
IActivityRepository),Infrastructure 层去实现它。这样,业务逻辑就不需要知道你用的是 MyBatis 还是 Hibernate,甚至换成 MongoDB,业务逻辑一行代码都不用改。
-
-
模型分离(PO vs Entity):
-
DAO 操作的是 PO:为了迎合数据库,可能有很多无关字段(如
is_deleted,create_time,update_time),或者是扁平化的结构。 -
Domain 需要的是 Entity:为了迎合业务,可能有丰富的行为方法(比如
activity.checkStatus()),或者复杂的聚合结构(一个对象里包含另一个对象 List)。 -
Repository 的实现类负责在两者之间做数据清洗和转换。
-
4. 总结图解
结合你的截图,数据流向是这样的:
简单一句话总结
-
DAO:是数据库的代言人,说的是“SQL 语言”(表、行、列)。
-
IActivityRepository:是业务逻辑的代言人,说的是“业务语言”(活动、抽奖、用户)。
-
Repository 实现类:是翻译官,把 DAO 查出来的“数据”翻译成业务需要的“对象”。
2.DAO PO DO
-
DAO (Data Access Object):
-
这是一个老牌的、通用的设计模式概念。
-
它的意思是“数据访问对象”。
-
在早期的 Java (JDBC, Hibernate) 时代,我们习惯叫它
UserDao,实现类叫UserDaoImpl。
-
-
Mapper:
-
这是 MyBatis 框架 特有的叫法。
-
MyBatis 觉得“映射(Map)”这个词更准确——把 Java 方法映射成 SQL 语句。
-
所以在 MyBatis 项目里,我们通常创建接口叫
UserMapper。
-
| 缩写 | 全称 | 中文名 | 它的身份 | 它的位置 |
|---|---|---|---|---|
| PO | Persistent Object | 持久化对象 | 数据库的影子。它跟数据库表是 1:1 对应的。表里有 user_id,它就有 userId;表里有 is_deleted,它就有 isDeleted。 | DAO层 / Mapper层 |
| DO | Data Object | 数据对象 | 通常等同于 PO。在阿里巴巴开发手册中,DO 就是数据库表对应的对象。但在某些别的架构里,它可能指“领域对象”,不过在你的项目中,它大概率就是 PO 的别名。 | DAO层 / Mapper层 |
PO ≈ DO。它们都是数据库表的 1:1 映射对象。