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

ksc*_*ann 5 rest spring spring-data-rest

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

比方说,我有两个类PostComment.两者都是实体,Post有一个@OneToMany List<Comment> comments.

因为Post显然是聚合根我想通过一个访问它PostRepository.如果我创建@RepositoryRestResource public interface PostRepository extends CrudRepository<Post, Long>REST访问Post工作正常.

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

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

gre*_*urn 2

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

这样,Post就不必担心对Comment.

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

  1. 获取 aPost及其Comment对象集合。
  2. 将您的新内容添加Comment到集合中。
  3. 新的Post及其更新的Comment对象集合放置到该资源中。

担心碰撞?这就是条件操作的用途,使用标准 HTTP 标头。如果您@VersionPost域对象添加基于属性,则每次使用Post新的给定更新时Comment,版本都会增加。

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

这样,您的PUT就可以使用 HTTP If-Match: <etag>标头进行条件化。如果其他人更新了该实体,您将收到 412 状态代码,表明您应该刷新并重试。

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