Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
对Spring数据DDD存储库模式感到困惑_Spring_Domain Driven Design_Nosql_Repository Pattern_Spring Data - Fatal编程技术网

对Spring数据DDD存储库模式感到困惑

对Spring数据DDD存储库模式感到困惑,spring,domain-driven-design,nosql,repository-pattern,spring-data,Spring,Domain Driven Design,Nosql,Repository Pattern,Spring Data,我对DDD存储库模式了解不多,但Spring中的实现让我感到困惑 public interface PersonRepository extends JpaRepository<Person, Long> { … } 公共接口PersonRepository扩展了JpaRepository{…} 由于接口扩展了JpaRepository(或MongodBRespository…),如果您从一个db更改为另一个db,那么您也必须更改接口 对我来说,有一个接口可以提供一些抽象,但这里

我对DDD存储库模式了解不多,但Spring中的实现让我感到困惑

public interface PersonRepository extends JpaRepository<Person, Long> { … }
公共接口PersonRepository扩展了JpaRepository{…} 由于接口扩展了JpaRepository(或MongodBRespository…),如果您从一个db更改为另一个db,那么您也必须更改接口

对我来说,有一个接口可以提供一些抽象,但这里并没有那么抽象


你知道为什么Spring数据是这样工作的吗

你是对的,接口是一种抽象,从外部的角度来看,它对所有实现类都是有效的

这就是这里发生的事情:

  • JPA存储库是所有JPA存储库的通用视图(适用于所有不同的实体),而MongoDBRepository适用于所有MongoDB实体
  • 但是JpaRepository和MongodBrespository没有任何共同之处,除了在这些通用超级接口中定义的内容:

    • org.springframework.data.repository.paging和sortingrepository
    • org.springframework.data.repository.repository
所以对我来说这很正常


如果您使用实现存储库的类,那么如果您希望能够从JPA实现切换到基于文档的实现,请使用PagingAndSortingRepository或Repository(抱歉,无论如何,我无法想象这样的用例)。当然,您的存储库实现应该实现正确的接口(JpaRepository、mongodbrespository),这取决于它是什么。

这篇博文中非常清楚地说明了这背后的原因

定义这个接口有两个目的:首先,通过扩展JpaRepository,我们得到了一系列通用的CRUD方法,允许保存帐户、删除帐户等等。其次,这将允许SpringDataJPA存储库基础设施扫描该接口的类路径,并为其创建Springbean

如果你不信任与消息来源如此接近的消息来源(双关语),那么阅读这篇文章也是个好主意

我不需要编写的是PersonRepository接口的实现。Spring将创建此接口的实现,并使PersonRepository bean可用于自动连接到我的服务类中。PersonRepository bean将具有所有标准CRUD方法(将是事务性的),并返回Person对象或Person对象的集合。因此,通过使用SpringDataJPA,我节省了编写自己的实现类的时间


在Spring数据发布之前,由于以下原因,我们要求用户扩展
JpaRepository

  • 类路径扫描基础设施只拾取扩展该接口的接口,因为可以并行使用Spring Data JPA和Spring Data Mongo,并将它们都指向同一个包—不清楚为哪个存储创建代理。然而,由于RC1,我们只是将这一负担留给了开发人员,因为我们认为这是一个非常奇特的案例,仅使用
    存储库
    crudepository
    或类似工具的好处超过了您在刚刚描述的案例中必须付出的努力。您可以在名称空间中使用
    exclude
    include
    元素来获得对此的细粒度控制
  • 在M2之前,我们通过重新定义CRUD方法并用
    @Transactional
    注释它们,将事务性应用于CRUD方法。这一决定又是由
    AnnotationTransactionAttributeSource
    用于查找事务配置的算法驱动的。因为我们希望通过在具体的存储库界面中重新定义CRUD方法并在其上应用
    @Transactional
    ,为用户提供重新配置事务的可能性。对于RC1,我们决定实现一个定制的
    TransactionAttributeSource
    ,以便能够将注释移回存储库CRUD实现
  • 长话短说,这里是它的归结:

    从RC1开始,不再需要扩展特定于商店的存储库接口,除非您想

  • 在更核心的存储库接口中,使用基于
    List
    的对
    findAll(…)
    的访问,而不是基于
    Iterable
    的访问(尽管您只需在公共基本接口中重新声明相关方法即可返回
    List
  • 您希望使用JPA特定的方法,如
    saveAndFlush(…)
    等等
  • 通常,自RC1以来,您在CRUD方法的公开方面更加灵活,因为您甚至只能扩展
    存储库
    标记接口,并有选择地添加要公开的CRUD方法。由于支持实现仍将实现
    分页和排序存储库
    的所有方法,因此我们仍然可以将调用路由到实例:

    public interface MyBaseRepository<T, ID extends Serializable> extends Repository<T, ID> {
    
      List<T> findAll();
    
      T findOne(ID id);
    }
    
    public interface UserRepository extends MyBaseRepository<User, Long> {
    
      List<T> findByUsername(String username);
    }
    
    公共接口MyBaseRepository扩展了存储库{ 列出findAll(); T findOne(ID); } 公共接口UserRepository扩展了MyBaseRepository{ 列出findByUsername(字符串用户名); } 在该示例中,我们定义了
    MyBaseRepository
    仅公开
    findAll()
    findOne(…)
    (将路由到实现CRUD方法的实例中)以及向两个CRUD方法添加查找器方法的具体存储库


    有关该主题的更多详细信息,请参阅。

    实际上,如果您在界面中知道存储库实现是给定类型的,那么为什么要使用界面呢?但我想和你一样,很难做得更好……我认为/期望从RDBMS到面向文档的存储的更改需要对对象/域模型进行重大更改。不管怎样,持久性抽象都会以某种方式泄漏。总是。如果可以的话