存储库模式与ORM

时间:2012-04-14 17:01:27

标签: php orm repository-pattern

拥有ORM时,存储库模式有什么用处?

实施例。假设我有以下(虚构)表:

表:用户

pk_user_id
fk_userrole_id
username

表:用户名

fk_userrole_id
role

现在有了一个orm,我可以简单地把它放在一个模型文件中:

$user = ORM::load('users', $id);

现在$ user已经是我的对象,很容易延迟加载:

(如果事情是自动单数/复数,会更好)

foreach ( $user->userroles()->role as $role )
{
    echo $role;
}

现在使用Repository模式我必须为Users创建一个存储库,为Roles创建一个存储库。存储库还需要各种函数来为我检索数据并存储它。此外,它需要与Entity模型一起使用。所以我也必须创造所有这些。

对我来说,看起来很多东西呢...当我可以简单地获得像上面描述的ORM数据。而且我可以轻松存储它:

ORM ::存储($用户);

在这种情况下,它不仅会将用户对象存储到数据库中,还会将对“角色”对象所做的任何更改存储起来。所以不需要像存储库模式那样需要任何额外的工作......


所以我的问题基本上是,为什么我要使用带有ORM的存储库模式?我已经看过教程在哪里使用该模式(与Doctrine一样)。但它对我来说真的没有任何意义......任何人都可以解释它与ORM的结合使用...... ??

2 个答案:

答案 0 :(得分:6)

ORM是存储库的实现细节。 ORM使得以OOP友好方式访问db表变得容易。就是这样。

存储库抽象持久性访问,无论存储是什么。这是它的目的。事实上,您使用db或xml文件或ORM并不重要。存储库允许应用程序的其余部分忽略持久性详细信息。这样,您可以通过模拟或存根轻松测试应用程序,并且可以根据需要更改存储。你可能会使用MySql,明天你会想要使用NoSql或云存储。用ORM做到这一点!

存储库处理域/业务对象(从应用程序的角度来看),ORM处理数据库对象。业务对象不是数据库对象,首先是行为,第二个是美化的DTO,它只保存数据。

修改 您可能会说存储库和ORM都抽象访问数据,但是恶魔在细节中。存储库抽象访问所有存储问题,而ORM抽象访问特定RDBMS

简而言之,Repository和ORM具有不同的用途,正如我上面所说,ORM始终是回购的实现细节。

您还可以查看this post有关存储库模式的更多详细信息。

答案 1 :(得分:0)

ORM和存储库模式...... 取决于设置。

  1. 如果您使用ORM实体作为域图层,请不要使用任何存储库。
  2. 如果您有一个单独的域模型,并且需要从该模型映射到ORM实体,从而执行保存,那么存储库就是您所需要的。
  3. 您找到的更多详细信息here(但必须登录到链接)。另外,要了解其中的差异,请查看存储库模式的definition

    大多数人使用他们称之为存储库的类,但根本不是存储库,只是查询类 - 如果你决定使用它,这就是你应该放置查询的方式/位置#1选项(请参阅上面的回答)。在这种情况下,请确保不要从该查询类公开DbContext或ISession,也不要从那里公开CUD方法 - 记住,查询类!

    #2选项很难。如果你做一个真正的存储库,存储库接口上的所有输入和输出都将包含明确的域类(并且没有与数据库相关的对象)。禁止从那里公开ORM映射类或ORM体系结构相关对象。还会有一个Save方法。这些存储库也可能包含查询,但与查询类不同,这些存储库将执行更多操作 - 它们将采用域聚合(实体集合和树)并通过将这些类映射到ORM类并在ORM上执行保存来将它们保存到DB。这种样式(#2)不需要使用ORM,存储库模式主要用于ADO.NET(任何类型的数据访问)。

    无论如何,这两个选项是我们可以做的两个极端。 很多人使用ORM存储库,但是他们只是添加了一个没有实际功能的额外代码层,唯一真正的功能是查询类就像行为一样。

    当有人谈论UnitOfWork时,我也要小心,特别是对于ORM。几乎互联网上的每一个样本都是架构方面的失败。如果你需要UoW,为什么不使用TransactionScope(只是确保你有一个默认包含Serializable事务以外的包装器)。在99.9%的情况下,您不需要管理2组独立的数据更改(因此需要2组OuW),因此TransactionScope将成为.NET的理想选择 - 对于PHP我会寻找一些开放会话视图实现......