我需要为哪些实体创建 Spring Data 存储库?
Posted
技术标签:
【中文标题】我需要为哪些实体创建 Spring Data 存储库?【英文标题】:Which entities do I need to create Spring Data repositories for? 【发布时间】:2015-12-04 13:04:36 【问题描述】:在 Spring Data JPA 的“入门”示例中,我们创建了一个扩展 CrudRepository 的接口。但是它只处理一个实体:
import org.springframework.data.repository.CrudRepository;
interface MyEntityRepository extends CrudRepository<MyEntity, Long>
// methods...
在现实世界的应用程序中,有很多实体(表),我们需要对它们进行 CRUD 操作。将 Spring Data JPA 存储库与多个(相关或不相关)实体一起使用的正确方法是什么?
我是否必须为每个实体创建接口并逐个自动装配它们(现在这听起来很疯狂)?
【问题讨论】:
是的,“我是否必须为每个实体创建接口并逐个自动装配它们”是对的。但是您必须为需要对其执行 SQL 操作的所有表创建一个存储库。 谢谢@Jens,但如果我有 10 个实体,创建 10 个接口并自动连接它们使用不是很奇怪吗?这样做的正确方法是什么?有没有其他的类或接口来概括它们? Are you supposed to have one repository per table in JPA?的可能重复 【参考方案1】:Spring Data 使用领域驱动设计中定义的存储库概念。存储库基本上代表聚合根的集合,它们又是您的一些实体,您将访问它们并对其他实体实施业务约束。例如。如果您有一个由LineItem
s 组成的Order
,则Order
将是聚合根,因为它控制LineItem
s 等的生命周期。因此,您将为Order
定义一个存储库,但是不适用于LineItem
。因此,到目前为止,并非所有实体都会为其创建存储库。决定哪些实体成为聚合根基本上是域建模中的一个重要部分。
另一方面是存储库通常由持久性机制支持,并且您不希望将业务逻辑直接编码到持久性 API 以使其可测试,而无需处理持久性 API。这意味着,存储库将包含查询方法,这些方法基本上代表集合中所有聚合根的子集,并由特定于存储的查询实现支持。这只能以按聚合根的方式实现。
第三个也是最后一个方面是存储库可以帮助您更轻松地限制对持久性操作的访问,因为您可以使用例如包范围强制客户端甚至使用专用服务,并且基本上隐藏某个包中某个域对象的所有持久性操作。使用像 EntityManager
这样的通用持久性 API,您将无法控制谁实际从系统中的任何位置读取了什么内容,因为它只能持久化持久性上下文中的每种类型。
总结一下:存储库代表聚合的集合,并允许访问该集合的专用子集。 Spring Data 使创建这些尽可能容易,替代方案在架构上不太理想(参见上面的推理)或更繁琐(如果它们必须手动实现。为哪些实体创建存储库取决于您如何对域建模,其中哪些是聚合根。
【讨论】:
非常感谢。所以我仍然理解这一点:我有#N 个实体,所以我必须创建#N 个存储库接口,并将它们一一放入服务 bean 或其他 bean 作为@Autowired。我仍然无法理解这句话的含义:100 个存储库接口,用于 100 个实体和 100 个自动装配的 bean。 是的,我做到了,也许是 3 次。再读一遍,我明白领域驱动设计让我们强迫这样的架构。我阅读了您对同一问题的其他答案:***.com/a/21277087/169534 如果我误解了,这意味着有办法做到这一点。这是什么?【参考方案2】:你是对的。对于要使用 Spring Data 的每个实体,您需要创建一个扩展存储库接口之一的接口,然后将该接口自动装配到您的类中。对于每个要对其执行 crud/query 操作的实体,您只需要其中一个。如果存在通过级联关系创建/管理的另一个实体中包含的实体,则无需为该实体显式创建存储库。
就您的观点而言,必须为每个实体创建一个接口并自动装配它可能看起来有点冗长,但这就是 Spring Data 的设计方式,并且是它能够自动为您生成数据访问代码的原因。如果您想编写自己的数据层,显然不必这样做。
【讨论】:
谢谢。那么,我应该摆脱 crudrepository 的方式并采用旧的基本 EntityManager 方法吗? @YasinOkumus 我不关注...可能值得就该主题提出一个新问题:)以上是关于我需要为哪些实体创建 Spring Data 存储库?的主要内容,如果未能解决你的问题,请参考以下文章
在 Spring Data JPA 中,如何在运行时添加实体?