例如,假设您具有以下表/关系:Customer – > 1..n帐户 – >特点
哪个功能可以是支票簿,或一些高级产品,如免费旅游保险.
那么我想做getCustomersForFeature()来检索所有具有免费旅游保险帐户的客户.
使用ActiveRecord或数据访问对象似乎不适合,因为这些通常集中在每个表的一个类;同样适用于Data Mapper.我意识到我可以把它分解成每个表的操作,例如getAccountsForFeature()和getCustomersForAccount(),但我想在一个命中进行检索.
如果我们要“弯曲”一类表格模式并使用数据访问对象模式,比如说getCustomersForFeature()方法是在CustomerDAO还是FeatureDAO上运行的?但是这并不适合我,因为你会用其他表的知识污染你的DAO.
请提出建议
解决方法
我认为ActiveRecord和他们的ilk可以用于单个表的简单查询,但尝试强制使用这些模式进行复杂查询太困难了.幸运的是,我们已经有一个简洁的域特定语言,可以用来指定复杂的查询:sql.
所以在你的Model类中,你将有方法来执行逻辑应用程序级的任务,比如getCustomersForFeature().在该方法的代码中,您应该编写一个特定的查询,无论是使用ActiveRecord方法还是使用直sql(如果需要).因此,您的数据库的具体设计将封装在Model类中的一个位置.
这意味着我们需要打破模型和表之间的耦合.模型和ActiveRecord类之间的OO关系不是IS-A – 它是HAS-A(或许多).
回复你的评论:那么我们的模型是什么?如果您的应用程序主要需要与客户一起作为一个实体,并将功能视为客户的属性,那么是的,您的Model将是客户,并且会隐藏功能存储在数据库中的单独表中的事实.客户模型将内部使用ActiveRecord或简单sql来收集所需的数据,以提供具有关联的多值属性的客户的复杂对象的完整视图.
但是,如果您的应用程序也需要直接使用功能呢?例如,管理员的屏幕,您可以根据功能获取报告或创建新功能.然后,通过客户模型访问功能将变得笨拙.所以你需要一个功能模型.只有它有不同的方法才能实现您需要使用的功能.
每个模型类都应该公开一个API,只需要使用该模型所需要的东西.没有必要甚至是对称的.只是因为您的客户模型可以获取具有特定功能的所有客户,并不一定意味着您的功能模型需要获取给定客户的所有功能.遵循YAGNI规则.
但是,在您创建了客户模型和功能模型之后,这不会导致重复了解表之间关系的逻辑吗?是的,可以的.这是object-relational impedance mismatch的范围内的许多问题之一.