现在,如果涉及复杂的聚合根,我无法获得Spring Data REST背后的概念。如果我正确理解域驱动设计(这是AFAIK弹簧数据的基本原理?),那么只能通过存储库公开聚合根。
假设我有两个课程Post
和Comment
。两者都是实体,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}
?
答案 0 :(得分:0)
对于初学者来说,如果Comment
有一些约束,那么我会把这个约束放在构造函数调用中。这样,您就不依赖任何外部验证框架或机制来强制执行您的要求。如果您被驱动到基于setter的解决方案(例如通过Jackson),那么您也可以将这些约束放在setter中。
这样,Post
不必担心会对Comment
强制执行约束。
此外,如果您使用Spring Data REST并且只定义PostRepository
,由于注释的生命周期共同链接到聚合根Post
,因此流程应为:
Post
及其Comment
个对象的集合。Comment
附加到收藏集。Post
及其更新的Comment
个对象集合到该资源。担心碰撞?这就是conditional operations所使用的标准HTTP标头。如果您向@Version
域对象添加基于Post
的属性,则每次使用新Post
更新给定Comment
时,版本都会增加。
当你获取资源时,Spring Data REST将包含一个E-Tag标题。
这样,您的 PUT 可以使用HTTP If-Match:&lt; etag&gt; 标头进行条件化。如果其他人更新了该实体,您将获得412状态代码,表示您应该刷新并重试。
注意:这些条件操作适用于 PUT , PATCH 和 DELETE 来电。