我有两个型号:User
和 Room
.一个用户属于多个房间,一个房间有多个用户。
目前我有
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/