我对DDD很新。我已经看到了许多使用泛型AggregateId(带有包含GUID的String)作为聚合根的键的示例项目。
我想知道如何在OneToMany关系中引用子节点的aggregateRoot。
假设有一个Order AggregateRoot和一个OrderLine。在GUID旁边有一个额外生成的(例如序列)id是否明智,所以OrderLine可以在数据库级别引用它?或者是orderLine的外键来订购GUID?是否有性能影响?
例如
BaseAggregateRoot:
@MappedSuperclass
public abstract class BaseAggregateRoot {
@EmbeddedId
@AttributeOverrides({
@AttributeOverride
(name = "idValue", column = @Column(name = "aggregateId", nullable = false))
})
protected AggregateId aggregateId;
...
订单:
@Entity
public class Order extends BaseAggregateRoot{
// is this ID necessary?
@Id
@GeneratedValue(generator = "OrderSequenceGenerator")
@SequenceGenerator(name = "OrderSequenceGenerator", sequenceName = "ORD_SEQ1", allocationSize = 1)
@Column(name = "ord_seq")
private Long id;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinColumn(name = "aggregateId") <-- should this point to ID or aggregateId?
private List<OrderLine> orderLines;
答案 0 :(得分:1)
首先,我想澄清DDD是关于域建模的,并且与 域的持久性无关。它可能存在于数据库中,但也可能存在于文本文件中。从域建模的角度来看,实体与其他实体相关的实体(以及如何)很重要,但通常不关联它们在关系数据库中的相关性。也就是说,问销售代表。订单项目如何识别其所属的订单,他会问你回报你的错误。
性能方面,使用GUID作为密钥存在一些风险。随机生成的GUID不适用于聚簇索引。最好使用顺序生成算法,并让数据库为您提供这些GUID。以下是有关此主题的讨论的链接:
What are the performance improvement of Sequential Guid over standard Guid?
我建议你特别阅读this answer。我同意Dan的观点,即连续的GUID缺少重点。
从关系上讲,对同一记录有两个标识符似乎是不必要的,而且通常是不明智的。我建议你选一个。所以,如果你的项目中存在GUID,那么你就会陷入困境。看看是否可以通过顺序生成它们来将它们用作键。然后,您可以删除@Id Long id
。如果没有,请将@EmbeddedId
替换为@Column
注释。
希望这有帮助,
祝你好运