对Spring数据DDD存储库模式感到困惑
我对DDD存储库模式了解不多,但Spring中的实现让我感到困惑对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,那么您也必须更改接口 对我来说,有一个接口可以提供一些抽象,但这里
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
:
存储库
,crudepository
或类似工具的好处超过了您在刚刚描述的案例中必须付出的努力。您可以在名称空间中使用exclude
和include
元素来获得对此的细粒度控制@Transactional
注释它们,将事务性应用于CRUD方法。这一决定又是由AnnotationTransactionAttributeSource
用于查找事务配置的算法驱动的。因为我们希望通过在具体的存储库界面中重新定义CRUD方法并在其上应用@Transactional
,为用户提供重新配置事务的可能性。对于RC1,我们决定实现一个定制的TransactionAttributeSource
,以便能够将注释移回存储库CRUD实现List
的对findAll(…)
的访问,而不是基于Iterable
的访问(尽管您只需在公共基本接口中重新声明相关方法即可返回List
)saveAndFlush(…)
等等存储库
标记接口,并有选择地添加要公开的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到面向文档的存储的更改需要对对象/域模型进行重大更改。不管怎样,持久性抽象都会以某种方式泄漏。总是。如果可以的话