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

时间:2015-11-10 08:53:02

标签: spring rest spring-data-rest

现在,如果涉及复杂的聚合根,我无法获得Spring Data REST背后的概念。如果我正确理解域驱动设计(这是AFAIK弹簧数据的基本原理?),那么只能通过存储库公开聚合根。

假设我有两个课程PostComment。两者都是实体,Post有@OneToMany List<Comment> comments

由于Post显然是聚合根,我想通过PostRepository访问它。如果我创建@RepositoryRestResource public interface PostRepository extends CrudRepository<Post, Long>Post的REST访问权限正常。

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

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

1 个答案:

答案 0 :(得分:0)

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

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

此外,如果您使用Spring Data REST并且只定义PostRepository,由于注释的生命周期共同链接到聚合根Post,因此流程应为:

  1. 获取Post及其Comment个对象的集合。
  2. 将新Comment附加到收藏集。
  3. PUT Post及其更新的Comment个对象集合到该资源。
  4. 担心碰撞?这就是conditional operations所使用的标准HTTP标头。如果您向@Version域对象添加基于Post的属性,则每次使用新Post更新给定Comment时,版本都会增加。

    当你获取资源时,Spring Data REST将包含一个E-Tag标题。

    这样,您的 PUT 可以使用HTTP If-Match:&lt; etag&gt; 标头进行条件化。如果其他人更新了该实体,您将获得412状态代码,表示您应该刷新并重试。

    注意:这些条件操作适用于 PUT PATCH DELETE 来电。