ORM / 如何处理领域对象和持久化对象之间的对应关系?

4
在应用程序中,至少有两种处理领域对象持久性和ORM的方法。
  • 使用某种ORM(XML或注释)将领域对象直接映射到持久性
  • 如果您的领域和持久模型(表列)之间存在很多阻抗不匹配,则进行关注点分离。这意味着,领域对象是持久性无关的,并且存在一些转换到相应的持久对象,后者映射到ORM。
作为纯DDD开发人员应该知道,领域不应受到数据库需求的驱动,因此在我的项目中,我使用了这种关注点分离。有人会想到YAGNI,有人会说“很棒”(就像这里一样)。根据我的可重用性需求,我的项目将需要一些不同的数据库,因此我选择了我的领域模型和持久模型之间的关注点分离。 但是我遇到了一个问题(某种性能损失),与Spring-Data有关。 这可能是一个细节,但假设一个ORM没有merge或任何相关功能来重新连接分离的实体到当前事务。

为了理解,让我们假设这个概念上的Java代码:

@Transaction
public void participateToMeeting(String userId, String meetingId){
  User user = userRepository.ofId(userId);  //returns a User domain type
  Meeting meeting = meetingRepository.ofId(meetingId); //returns a Meeting domain type
  if(user != null && meeting != null) {
    user.participate(meeting);    // as attached entity, this would automatically persist the relationship
  }
}

但是,如果从现在开始,坚持发生在持久模型上,而不是直接在域模型上进行,我们将失去附着性,因为在从域转换为持久对象时(实际上,存储库现在将处理持久对象(而不是直接处理域模型),并仅将结果转换为域对象作为返回类型),managedEntity状态会丢失。
    @Transaction
        public void participateToMeeting(String userId, String meetingId){
          User user = userRepository.ofId(userId);  //returns a User domain type (converted from UserPO to User)
          Meeting meeting = meetingRepository.ofId(meetingId); //returns a Meeting domain type (converted from MeetingPO to UserPO)
          if(user != null && meeting != null) {
            userRepository.participateToMeeting(user, meeting); 
//although not conventional, adding this kind of method allows to convert User and Meeting to some persistent object: UserPO and MeetingPO, before proceeding to persistence
          }
        }

这里有个问题: 在我的基础设施层中,从User转换为UserPO时,我丢失了实体“attachment”。因此,在userRepository.participateToMeeting方法中,我必须再次从数据库中检索UserPOMeetingPO(使它们附加)...因此涉及了两个额外的请求。 有没有更好的做法来处理领域对象/持久化对象的转换而不会有性能损失?
1个回答

4
我不同意这篇文章的观点。虽然我认为领域模型和持久化模型之间的问题确实不同,但ORM的整个目的就是在领域模型和持久化模型之间进行映射。由于ORM应该提供这种映射,因此创建一个额外的类层次结构来促进映射是过度的,可能会导致您所描述的问题。事实上,领域模型类似于数据模型,绝非仅仅是巧合。相反,它们都代表了同一领域的方面,因此应该具有高度的对应性。ORM旨在解决对象模型与相应关系模型之间的不匹配。有些情况下可能会出现映射困难的情况,但在NHibernate中,可以通过实现自定义用户类型来处理组件映射。

我同意你的观点。然而,正如这篇文章所引发的讨论,Spring-Data(在这种情况下是针对Neo4j的,但我想即使是Spring-Data一般也是如此)不支持(容易地)嵌套类型:https://groups.google.com/forum/#!topic/neo4j/Uc15iftJd_E 因此,如果我想要存储一个Meeting聚合根,其中包含一个Schedule值对象,该值对象包含两个字段:startDateendDate,并将它们分别存储在两个不同的元素中(在我的情况下是“节点”),那么我就会陷入困境。这就是为什么我更喜欢保持这种关注点的分离,即使这会导致额外的努力。 - Mik378

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接