当前位置: 首页 > 知识库问答 >
问题:

利用通用存储库接口

钦楚青
2023-03-14

我见过存储库模式的各种用法。我倾向于一种我很少看到的模式,我想知道这是否有充分的理由。

        Class Teacher : IPerson
        {
            Private IRepository myRepository;

            Internal Teacher(IRepostory repo){
                This.myRepository = repo;
            }

            Public overrides void Save(){
                Repo.Save(this);
            }
        }

例子:

 IPerson p = DataAccess.GetPersonFromId(id);
 p.Name = "Bill";
 p.Save();

利益

  1. 构造函数将是内部的,只能通过工厂模式访问,所以我不担心这里的复杂性。
  2. IPerson 强制实现 Save() 方法,但教师不需要知道它是如何持久化的
  3. 工作原理类似于实体框架代理对象
  4. 我可以在 Iperson 对象上调用 Save(),而无需知道它是老师
  5. 应用-

欺骗

>

  • 业务对象不再是普通的旧C#对象

    对实体存储库的任何更改都可能需要更改“个人”界面。

    我应该对IFactory应用相同的模式吗?我们是否继续注射服务?

            IPerson p = DataAccess.GetPersonFromId(id);
            IRepostory repo = DataAccess.GetRepositority()
            p.Name = "Bill";
            repo.Save(p);
    

    利益

    1. 似乎是更简单的做事方式

    欺骗

    1. 我不能很好地利用可用于所有派生类型的通用存储库。我想使用一个可以采用Person Type并知道如何持久化它的Irepostory接口。

    总结

    我倾向于模式1,但我在那里看到的几乎每个示例都使用模式2的版本。

    主要目标是我不想在应用层的任何地方使用TeacherRepository。我想完全依靠IRepository。然而,我似乎无法在模式2中做到这一点,因为Save()需要知道它与老师的关系,才能正确地持久化数据。

    有没有其他独特的模式可以让我使用通用存储库?

  • 共有1个答案

    彭坚壁
    2023-03-14

    关于模式 1:它与使域对象不仅不知道底层存储类型,而且不知道它必须存储在某个地方的简单事实的原则相矛盾。更重要的是,通过应用模式 1,您打破了单一责任原则:您将有两个原因来更改域对象:业务逻辑和存储。而且,从行为的角度来看,得救不是老师的责任,而是存储库的责任。因此,恕我直言,利弊不再需要讨论。注意:并非所有框架都遵循良好的OOP设计。在大多数情况下,考虑使用活动记录的ORM。他们正在使用类似“班级教师扩展ActiveRecord”之类的东西。或者强加“每桌一课”等条件。那么,你怎么看?

    关于模式 2 和您的问题:在这里,您正在尝试强制执行我上面提到的内容:以某种方式标准化数据访问工作流,以便能够存储任何类型的域对象属性和构造。对象关系映射...你可以这样做,但你必须处理很多缺点。而且,您必须考虑您的业务在业务逻辑和存储结构方面的重要性。更不用说当您必须处理具有更高复杂程度的查询时缺乏灵活性。最后 - 我听说 - 你甚至会发现有些任务实际上是不可能解决的。

    因此,我的建议是让“普通旧”业务对象完全不知道存储,为它们定义特定的存储库,并从外部(例如通过服务)将它们“绑定在一起”。

    实际上,存储库是在所谓的数据映射器之上的数据访问抽象层。数据映射器仅与基础数据库通信。在你的问题中,你可以在这里找到一个很好的论证:

    • 数据映射器模式:类设计

    这里还有一些其他的资源:

    • MVC中的模型结构
    • SRP公司

    祝你好运.

     类似资料:
    • 我们正在研究一个包含大量DB表的Restful项目。虽然对这些表的操作几乎相同,主要是插入/更新/删除/提取(insert/update/delete/fetch)。 我的问题是: 我们是否必须为我们创建的每一个实体(域类)创建一个存储库(扩展JpaRepository),或者,有一个选项可以为所有实体创建一个能够处理上述所有功能的GenericRepository?即为所有人提供一个单一的Gen

    • 我们使用RDF4J(以前的sesame)框架来运行sparql查询到远程GraphDB三重存储。 这可以通过rdf4j HTTPRepository接口成功地工作,该接口使用Graphdb服务器的URL和存储库ID,但在使用rdf4j SPARQLRepository接口时失败,该接口将Sparlqendpointurl作为参数。 在运行查询时,我们在查询验证中得到一个异常 “获取服务器协议失败;

    • 我正在尝试实现一个简单的REST服务,该服务基于具有Spring启动和Spring数据Rest的JPA存储库。(请参阅此教程)如果将以下代码与 gradle 一起使用,则运行良好: 为了让事情变得更简单,我使用Spring boot CLI(“Spring run”命令)尝试了相同的代码。 不幸的是,这似乎不起作用@RepositoryRestResource似乎无法像@RestControlle

    • 是否有一种方法可以使通用Spring数据JPA存储库正确处理类似的方法?例如只返回狗,而不返回所有动物?或者至少,最好的变通方法是什么? 它的工作几乎完美,保存每一个动物在自己的桌子上,等等。唯一的问题是:同时返回水豚和狗。这个答案解释说: 这只有在域类使用单表继承时才起作用。我们在引导时能得到的关于domain类的唯一信息是它将是Product对象。因此,对于像findAll()甚至findBy

    • 以下是我的模型:- 我的存储库和服务:- 控制器:- org.springframework.beans.factory.beanCreationException:创建类路径资源[org/springframework/boot/autocconfigure/orm/jpa/hibernatejpaconfiguration.class]中定义的名为“Entity ManagerFactory”

    • 我正在尝试将通用Jpa规范与Spring启动一起使用,但出现了这个问题。 在我的代码中,我试图使用模块概念,所以我有5个模块(实体、dao、服务、web和前端,带角度),所以这是我的代码: 我的通用Jpa规范接口。 存储库示例。 服务 和控制器