DAO 层和 ORM,能区分,但又不完全能区分,我裂开了

2021-05-06 14:22:54 +08:00
 waibunleung

desc:是这样的,小弟从 php 转到 go 一个月时间不够,项目的目录结构需要自己搭建。于是就找网上的项目组织目录参考,发现有一部分目录结构里有 dao 层的分层概念。这个在 java 里面比较常见,在 php 中用得比较多的是 orm,不知道 go 中是不是也适合这样搞。

于是引起了我一顿梳理 dao 和 orm 之间的关系。但仍有如下疑问:

  1. 究竟项目使用了 orm 之后,还需不需要再分一层 DAO 层出来?如果要分,此时的 DAO 层里面写的是什么逻辑?求 demo 举例
  2. ORM 不是正好替代了 DAO 的角色吗?还是说 DAO 可以通过 ORM 来实现?此时 DAO 层的实现是怎么样的?在 ORM 外面包一层,意义在哪里?
  3. 在项目代码分层上(语言无关),DAO 和 ORM 分别是什么层面上的东西?

真的纠结了三四天了,每天看完都有不同的结论,求大佬们指点一下你们在项目中是怎么划分的~

7498 次点击
所在节点    程序员
78 条回复
ychost
2021-05-06 14:27:40 +08:00
可以直接把 repository 注入到 Service 里面用,对于一些复杂的手工 SQL,包一个 Repository 再给 Service 用
waibunleung
2021-05-06 14:33:26 +08:00
@ychost 有 demo 吗?
waibunleung
2021-05-06 14:35:18 +08:00
@ychost 这里面说的 Repository 就是 DAO 层?
kop1989
2021-05-06 14:45:58 +08:00
DAO,一般叫数据访问层。
ORM,说的是对象关系映射。

这二者的描述角度不同。
一个是从控制操作角度描述,一个是从模型设计角度描述。

DAO 指的是对数据库表操作的方法封装。
而 ORM 指的是实体(类)与数据库表之间的对应关系。

所以:
1 、有了 ORM,是否还需要 DAO ?不一定,取决于你的设计,以及各个语言的 ORM 框架功能不同而决定。

举例:比如我需要输出表 A 的行数,如果是单纯的 ORM,那我就只能直接获取本表的所有内容,返回一个 List<A>,然后我在业务层再去获取 List<A>的 size 。这明显是效率非常低下的。于是我就可以通过 DAO 层单独编写封装 SQL 去获取表 A 的行数,返回。

2 、DAO 和 ORM 冲突么?不冲突。
Rwing
2021-05-06 14:57:19 +08:00
DAO 是代码分层的概念。
DAO 中使用 ORM 来进行数据访问,举个例子,假如某一天不想用 ORM 了,只需要替换掉 DAO 层中的实现即可。
题外话:其实如果用来写业务,GO 并不比其他语言拥有更好的开发效率。想不明白为什么这么多人转 GO
bigpigeon
2021-05-06 15:00:21 +08:00
我觉得看项目复杂度,如果一个项目 2 个人写,可以一个人负责数据访问一个人负责业务对接,那就应该分一层 DAO 出来,如果是一个人用了 ORM 就没必要搞一个 DAO 出来,不然你改起来会贼蛋疼,个人经验所得 ,顺手推下以前写的 ORM https://github.com/bigpigeon/toyorm
waibunleung
2021-05-06 15:11:47 +08:00
@kop1989 你的意思是,DAO 层可以通过 ORM 来实现?那 dao 层实现的函数一般类似怎么样的呢?是类似于这样的函数吗?
```php
function queryByContentAndCreatedBy($content, $createdBy){
$sql = "SELECT * FROM content WHERE title like '%".$content."%' AND created_by=?";
$sqlQuery = new SqlQuery($sql);
$sqlQuery->setNumber($createdBy);
return $this->getList($sqlQuery);
}

```
还是只是封装了简单的 CURD ?就是之前没有用过(或者用过不知道),看看看具体的 dao 实现是什么样的,或者说什么样的函数适合写到 dao 中。
kop1989
2021-05-06 15:19:46 +08:00
@waibunleung #7 没错,是这个意思。DAO 层可以通过 ORM 实现增删改查,也可以不通过。

至于说需要封装什么方法,这就要看你的程序业务需求而定了。
最基础的当然是增删改查。

关键在于多一层封装,就把数据控制逻辑和业务逻辑解耦了。
以后更换数据控制方法,比如从 ORM 变成 SQL,或者从 SQL 变成 ORM,甚至是更换数据库类型等,都不会对上层业务造成影响。
waibunleung
2021-05-06 15:20:37 +08:00
@Rwing dao 层通过 orm 来访问数据的话,那 dao 层的实现一般长什么样子呢?另外如果 dao 层的实现不够通用,那不是一种复杂的查询就要对应一个函数?这样 dao 里面每来一个复杂查询都新增一个函数吗?
kop1989
2021-05-06 15:20:44 +08:00
@waibunleung #7 这也就衍生出来说:DAO 层暴露出来的接口设计,一定要是业务驱动的,或者说是功能驱动的,而不能是技术驱动的。
waibunleung
2021-05-06 15:27:53 +08:00
@kop1989 dao 的实现一般是怎么样的?能否举个例子呢?说增删改查很模糊,没有具体感念
waibunleung
2021-05-06 15:31:02 +08:00
@bigpigeon 分一层 dao 出来,那 dao 里面具体些什么样的逻辑呢?能不能举个例子呢?
bthulu
2021-05-06 16:07:58 +08:00
orm 就是封装了一些 crud, 原本需要你手动 set 参数的, 你传个对象进去, 就根据对象字段名帮你映射到 sql 语句的?上. 然后再帮你把返回的数据按列名映射到 java 类字段上.
dao 就是原本你的 crud 直接写在业务方法里, 现在有人说 no, 你这样写不 cool, 你要把 crud 全部写到一个单独的类里, 这样 cool.
xiangwan
2021-05-06 16:22:24 +08:00
这个层怎么分,可以多看看那几个架构模式。什么 DDD 、洋葱、六边形、清晰等等。
DAO 是比较旧时代的水平分层里的概念
newtype0092
2021-05-06 16:52:06 +08:00
用用户信息举例:

DAO 屏蔽了数据获取的逻辑,只提供一个 getUser(id) 的方法,不管里面怎么实现,需要数据用这个方法取就行。

然后看 DAO 内部,可以用很多方法去实现。

最简单的方法,直接查库,query('select * from users where id = ' + id),然后返回数据,需要什么数据就直接写 SQL
ORM 就是把常用的 SQL 封装好,这样用里面提供的类似 getUserById(id) 的方法就能省掉上面的字符串拼接、参数处理、校验、返回数据格式化等问题,直接返回映射好的 object 。

当然,不一定所有数据都存在关系数据库里,也可能存在 nosql 数据库、磁盘文件甚至需要通过网络请求其他服务,但不管存在哪,为了最大限度的减少这些乱七八糟的逻辑对业务逻辑的影响,只提供统一的操作数据的接口,这个就是 DAO 干的活。
waibunleung
2021-05-06 17:05:43 +08:00
@bthulu 那有了 orm 就不需要 dao 了吧?
zjsxwc
2021-05-06 17:11:08 +08:00
当然是全都要,两者又不排斥。

ORM 是关系数据库表中每一行与面向对象语言每个实体类实例的映射。
DAO 是设计模式,把同类通表数据库操作都整理到一个类中。

实际上,ORM 的 Repository 就是 DAO 。

就是这么简单。
waibunleung
2021-05-06 17:12:59 +08:00
@newtype0092 假如我有一个根据用户活跃度排序输出用户列表的需求,此时 orm 并没有直接的方法,我就需要在 dao 层搞一个类似 getUsersByActiveOrder(limit, offset)这样的方法?那每来一个复杂的查询就需要在 dao 层增加一个方法,不管我 dao 的方法里面写的是原始 sql 还是用 orm,是这个意思吗?
waibunleung
2021-05-06 17:14:01 +08:00
@zjsxwc Repository 这个里面是怎么样的?有简单的例子举一下吗?
zjsxwc
2021-05-06 17:14:41 +08:00
大概也就只用过 ActiveRecord 这种没有 Repository 的 ORM 的人,会对 ORM 与 DAO 有疑惑吧

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/775162

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX