domain-driven-design - 在 ddd 上建立多对多关系模型

标签 domain-driven-design

我有两个型号:UserRoom .一个用户属于多个房间,一个房间有多个用户。
目前我有

public class User extends BasePersistable {

  private static final long serialVersionUID = 1492535311821424305L;

  @Column(nullable = false, unique = true)
  private String login;

  @Column(nullable = false)
  private Integer uid;

  @ManyToMany(targetEntity = Room.class)
  @JoinTable(name = "room_users", joinColumns = {@JoinColumn(name = "user_id")}, inverseJoinColumns = {@JoinColumn(name = "room_id")})
  private Set<Room> rooms = new HashSet<>();


public class Room extends AbstractAggregateRoot implements Serializable {

  private static final long serialVersionUID = 1L;

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @JsonIgnore
  private Long id;

  @ManyToMany(mappedBy = "rooms", targetEntity = User.class, cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REMOVE})
  @JsonIgnore
  private Set<User> users = new HashSet<>();

当用户登录时,我要么找到他,要么创建他,然后根据一些规则为他找到或创建房间。
对我来说,有两件事很清楚:
1)一个房间有很多消息,没有房间消息就不存在,因此,房间是一个聚合根。
2)User需要在房间范围外操作,因此User也应该是聚合根。

所以问题来了:我了解到聚合根不引用另一个聚合根(仅通过值对象)。聚合根应该包含它需要存在的所有内容,而不依赖于外部源(在这种情况下,用户聚合根)。

我怎样才能在他们之间建立这种关系?用户登录后,我如何创建我需要为他创建的房间?我在想我可以发布一个事件,然后基于此 (UserCreatedEvent) 创建房间......我的方向是否正确?

最佳答案

是的,您的方向是正确的。

对于跨越多个聚合的进程,您可以使用 Saga/Process manager .该组件通过监听相关事件(即 UserCreatedEvent )并将命令发送到相关聚合来工作。在您的情况下,Saga 会发送一个或多个 CreateRoom需要创建的每个房间的命令。

您应该记住,此过程最终是一致的,即从发出事件到发送命令之间存在时间延迟。

关于domain-driven-design - 在 ddd 上建立多对多关系模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46393406/

相关文章:

mysql - SQL模式设计和规范化

php - 您是否将存储库注入(inject)域对象?

.net - "ApplicationServices"是横切关注点 "stuff"的正确名称吗?

java - 另一个聚合根中的聚合根引用

entity - DDD 聚合 : Entity holding identifier to Non-Root Entity in another Aggregate

Java EE : Creating and deleting socket listeners dynamically from the domain model

architecture - 我可以从表示层访问存储库吗?

c# - 所有域实体对象的抽象基类

c# - DDD 使用事件或服务?

domain-driven-design - DDD、微服务和数据方向