使用Spring数据REST处理复杂的聚合根

使用Spring数据REST处理复杂的聚合根,spring,rest,spring-data-rest,Spring,Rest,Spring Data Rest,现在,如果涉及到复杂的聚合根,我无法理解SpringDataREST背后的概念。如果我正确理解域驱动设计(这是spring数据的基本原则吗?),那么您只能通过存储库公开聚合根 假设我有两个类Post和Comment。两者都是实体,Post有一个@OneToMany列表注释 由于Post显然是聚合根目录,我想通过PostRepository访问它。如果我创建@RepositoryRestResource公共接口PostRepository扩展crudepositoryREST访问Post工作正常

现在,如果涉及到复杂的聚合根,我无法理解SpringDataREST背后的概念。如果我正确理解域驱动设计(这是spring数据的基本原则吗?),那么您只能通过存储库公开聚合根

假设我有两个类
Post
Comment
。两者都是实体,Post有一个
@OneToMany列表注释

由于
Post
显然是聚合根目录,我想通过
PostRepository
访问它。如果我创建
@RepositoryRestResource公共接口PostRepository扩展crudepository
REST访问
Post
工作正常

现在,
comments
是renderd内联的,不像
/posts/{post}/comments
那样作为子资源公开。只有在我引入
CommentRepository
时才会发生这种情况(如果我想坚持使用DDD,就不应该这样做)


那么,如何将SpringDataREST正确地用于复杂的域对象呢?假设您必须检查所有注释总共不包含超过X个字符。这显然是由
Post
聚合根处理的一些不变量。将
Post.addComment()
的逻辑放在哪里?如何将其他类公开为子资源,以便我可以访问
/posts/{post}/comments/{comment}
,而不引入不必要的存储库?

对于初学者,如果
comment
上有一些约束,那么我会将该约束放在构造函数调用中。这样,您就不需要依赖任何外部验证框架或机制来强制执行您的需求。如果您被迫使用基于setter的解决方案(例如通过Jackson),那么您也可以将这些约束放在setter中

这样,
Post
就不必担心对
Comment
强制执行约束

此外,如果使用Spring数据REST并仅定义一个
PostRepository
,由于注释的生命周期与聚合根
Post
联合链接,因此流应该是:

  • 获取
    Post
    及其
    Comment
    对象的集合
  • 将新的
    注释添加到集合中
  • 将新的
    Post
    及其更新的
    Comment
    对象集合放入该资源
  • 担心碰撞?这就是使用标准HTTP头的目的。如果将基于
    @Version
    的属性添加到
    Post
    域对象,则每次使用新的
    注释更新给定的
    Post
    ,版本都会增加

    当您获取资源时,Spring数据REST将包含一个E-Tag头

    这样,您的PUT就可以通过HTTPIf Match:头条件化。如果其他人更新了实体,您将返回412状态代码,指示您应该刷新并重试


    注意:这些条件操作适用于PUTPATCHDELETE调用。

    查看这篇关于处理聚合对象的帖子: