从理论上讲,如果我们在聚合根级别上实现乐观并发(在AR中更改实体更改AR上的版本),并且假设我们使用时间戳作为版本属性(仅为了简单起见) - 时间轴应该是AR上的属性还是应该它是一方面读取模型的一部分,另一方面(例如,更新)是应用程序服务的单独参数,如:
[伪]
public class AppService{
.
.
.
public void UpdateSomething(UpdateModelDTO model, int timestamp)
{
repository.GetModel(model.Identifier);
model.UpdateSomething(model.something);
repository.ConcurrencySafeModelUpdate(model, timestamp);
}
}
我看到两者的利弊,但想知道哪个是书本解决方案?
[UPDATE]
要回答来自@ guillaume31的问题,我希望通常情况:
我不知道它是否重要,但我想承担创建/更新版本标识符本身的责任到我的数据库系统。
答案 0 :(得分:2)
我假设,否则你不会问这个问题,你使用你的域模型作为数据模型(即Hibernate实体),那么你已经在你的域模型中引入了基础设施问题,所以我建议继续并将时间戳添加到AR。
答案 1 :(得分:1)
除了与业务相关的问题外,Aggregate不应该关心任何其他问题。它应该是纯粹的,没有任何基础设施问题。
数据库/持久性中的version
列是基础结构问题,因此不应在Domain层的Aggregate类中反映出来。
P.S。使用时间戳进行乐观锁定很奇怪;你最好使用一个整数,每当一个Aggregate发生变异时,该整数会增加,并且当执行save
时,它应该具有(loaded-version + 1)。
public void UpdateSomething(UpdateModelDTO model)
{
(model, version) = repository.GetModel(model.Identifier);
model.UpdateSomething(something);
repository.ConcurrencySafeModelUpdate(model, version + 1);
}
答案 2 :(得分:0)
没有书本解决方案。有时,您的聚合中已经有一个适合该角色的字段(例如LastUpdatedOn
),有时您可以将其设为非域数据。出于性能原因,最好选择该字段作为获取聚合的同一查询的一部分。
某些ORM提供检测并发冲突的工具。某些DBMS可以自动为您创建和更新版本列。您应该在特定堆栈中寻找有关乐观并发的指导原则。