我对DDD存储库模式了解不多,但Spring中的实现让我很困惑。
public interface PersonRepository extends JpaRepository<Person, Long> { … }
当接口扩展JpaRepository(或MongoDBRepository ...)时,如果从一个db更改为另一个db,则还必须更改接口。
对我来说,一个接口可以提供一些抽象,但这里并没有那么抽象......
你知道为什么Spring-Data会这样吗?
答案 0 :(得分:11)
你是对的,从外部的角度来看,接口是关于所有实现类的工作的抽象。
这就是这里发生的事情:
但JpaRepository和MongoDBRepository没有任何共同之处,除了常见的超级接口中定义的东西:
所以对我而言看起来很正常。
如果您使用实现存储库的类,那么如果您希望能够从JPA实现切换到基于文档的实现,请使用PagingAndSortingRepository或Repository(抱歉,但我无法想象这样的用例 - 无论如何)。当然,您的Repository实现应该实现正确的接口(JpaRepository,MongoDBRepository),具体取决于它是什么。
答案 1 :(得分:7)
此博客文章http://blog.springsource.com/2011/02/10/getting-started-with-spring-data-jpa/中已明确说明了这背后的原因。
定义此接口有两个目的:首先,通过扩展JpaRepository,我们在我们的类型中获得了一堆通用的CRUD方法,允许保存帐户,删除它们等等。其次,这将允许Spring Data JPA存储库基础结构扫描此接口的类路径,并为其创建一个Spring bean。
如果你不信任来源如此接近来源(双关语),那么阅读这篇文章也是一个好主意http://www.brucephillips.name/blog/index.cfm/2011/3/25/Using-Spring-Data-JPA-To-Reduced-Data-Access-Coding。
我不需要编码的是PersonRepository接口的实现。 Spring将创建此接口的实现,并使PersonRepository bean可以自动连接到我的Service类中。 PersonRepository bean将具有所有标准CRUD方法(将是事务性的)并返回Person对象或Person对象的集合。因此,通过使用Spring Data JPA,我已经保存了自己编写的实现类。
答案 2 :(得分:3)
在Spring数据的M2之前,由于以下原因,我们要求用户扩展JpaRepository
:
Repository
,CrudRepository
或类似的权益,就可以超越您刚才所描述的努力。角落案件。您可以使用命名空间中的exclude
和include
元素来对此进行更精细的控制。@Transactional
注释它们来将事务性应用于CRUD方法。反过来,这个决定是由AnnotationTransactionAttributeSource
用于查找事务配置的算法驱动的。我们希望通过在具体的存储库界面中重新声明CRUD方法并在其上应用@Transactional
来为用户提供重新配置事务的可能性。对于RC1,我们决定实现自定义TransactionAttributeSource
,以便能够将注释移回存储库CRUD实现。长话短说,这就是它归结为:
从RC1开始,不再需要扩展商店特定的存储库界面,除了你想...
List
的{{1}}而不是findAll(…)
的访问权限(尽管您可以简单地在公共基础接口中重新声明相关方法也可以返回Iterable
)List
等。一般来说,自RC1以来你对CRUD方法的曝光要灵活得多,因为你甚至可以只扩展saveAndFlush(…)
标记界面并有选择地添加你想要公开的CRUD方法。由于支持实现仍将实现Repository
的所有方法,我们仍然可以将调用路由到实例:
PagingAndSortingRepository
在该示例中,我们将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()
(将被路由到实现CRUD方法的实例中)和具体的存储库,将finder方法添加到两个CRUD。
有关该主题的更多详细信息,请参阅reference documentation。