域对象和 DAO。如何从域对象中进行查询,但仍然有两个对象不知道彼此存在

Posted

技术标签:

【中文标题】域对象和 DAO。如何从域对象中进行查询,但仍然有两个对象不知道彼此存在【英文标题】:Domain Object and DAO. How to do queries from within the Domain Object but still having both objects not know each other exists 【发布时间】:2012-12-17 00:58:26 【问题描述】:

好的,我的 DomainObject/Model 名为 $user 和我的 $userDAO 对象。

到目前为止,当我需要执行 CRUD 操作(例如获取 $user 对象)时,我已经阅读过:

$user = $userDAO->fetchById($userId);

这将返回我的 $user 对象。

显然 DomainObject 不应该知道 DAO 对象存在,反之亦然,但是如果用户正在注册并且我运行 $user->register() 方法会怎样

$user->register($firstName, $lastName, $emailAddress, $username, $password etc.);

在该方法的某个地方,我需要检查所选用户名是否已被使用,并且与电子邮件地址相同。

我能想到的唯一方法是在我的$user 对象中拥有一个$userDAO 对象的实例,然后进行如下验证:

if($this->userDAO->isUsernameTaken($username)) 
    // the username is already in use

else 
    // continue on

但这会打破 DomainObject 不应该知道数据库内容的规则,反之亦然,但我认为 DomainObject 并不真正了解数据库内容,因为所有查询都在 DAO 对象中,它只是持有对对象的引用,但它不明确知道该对象中发生了什么。我是对还是错?

如果我做错了,我应该如何运行像 $user->register() 这样的方法,它需要在其中调用一些需要访问数据源但 DomainObject/Model 的数据库查询不允许知道专家说的任何数据源?

我今天在 Google 上浏览了页码,我以为我永远不必再浏览了,但我仍然找不到任何非常可靠的现实生活示例来说明该做什么,我开始发疯了,因为它放慢一切。

任何帮助将不胜感激。谢谢。

【问题讨论】:

【参考方案1】:

如果您从分层架构的角度考虑应用程序的架构,则需要在域层和 DAO 层之上再构建一层,让这两层保持原样。这个新层被一些人称为服务层或应用层。该服务层的工作是执行用例,例如“注册”一个新用户。例如,服务层中的一个类可能是 UserService,它执行与用户相关的用例,

class UserService 

private UserDao userDao;

// constructor
userSercie()



// registers a user
register($firstName, $lastName, $emailAddress, $username, $password etc.) 
    $user = $userDAO->fetchByName($username);
    if($user != null) 
         // the username is already in use
    
    else 
       // continue on
    

   

 // other service methods such as



为什么我们需要服务层?正是为了应对像您这样的问题,我们需要服务层。这样你可以看到我们可以保持不同模块之间的关注点分离。

【讨论】:

啊,是的,这就是我所缺少的,谢谢。但有一件事,如果$fetchByName() 方法在数据库中找到具有该用户名的行,它将返回一个$user 对象?如果我想检查提供的电子邮件地址是否已经存在,我是否使用了$fetchByEmail() 方法? 我使用了 fetchByName 这个名字,它通常是 CRUD 中的一个方法,除了 fetchById。但是,无论如何,这是一个例子来说明我关于服务方法的外观和行为的观点。当然,你可以有更多的 DAO 方法,例如 fetchByEmail() 等。但是,一般情况下,像 userDAO->isUsernameTaken($username) 这样的东西是不对的,执行这个检查不是 DAO 的责任,应该在服务层,使用 DAO,正如我已经展示的那样。 好的,谢谢,但不是只能执行userDAO->isUsernameTaken($username),它执行一个返回布尔值的小简单查询,正确的做法是$user = $userDAO->fetchByName($username);,如果一行将创建一个用户对象已返回,然后我通过执行if($user != null) 来检查用户名是否存在?对我来说,这似乎真的效率低下和矫枉过正。当我开始这样做时,我已经可以看到我将不得不让函数一直返回对象,而不仅仅是布尔值。 你意识到检查不是线程安全的吧?捕获唯一的数据库约束异常可能会更好。

以上是关于域对象和 DAO。如何从域对象中进行查询,但仍然有两个对象不知道彼此存在的主要内容,如果未能解决你的问题,请参考以下文章

从域对象调用 Grails 服务是否很糟糕? [关闭]

关于如何从域 (ORM) 对象映射到数据传输对象 (DTO) 的建议

将 wordpress 从域迁移到另一个域 - 但 URL 仍重定向到旧域

将 DAO 和域对象分开

我应该将 DTO 映射到客户端和服务器端的域实体/从域实体映射吗?

Struts2--day04