Design patterns 身份映射中的空密钥

Design patterns 身份映射中的空密钥,design-patterns,data-modeling,orm,Design Patterns,Data Modeling,Orm,我在身份映射中使用了一个域对象(键是对象的Id属性) 伪代码: map = new Mapping(); map[domainObj.Id] = 'foo'; 我观察对象以告诉我它何时已保存到数据库: domainObj.bind('saved', function() { map[domainObj.Id] = 'new foo!' }) 对于新对象,Id字段为空,在保存到数据库之前不会填充 这就是我的问题所在。对于新对象,查找“map[domainObj.Id]”失败,因为对象的

我在身份映射中使用了一个域对象(键是对象的
Id
属性)

伪代码:

map = new Mapping();
map[domainObj.Id] = 'foo';
我观察对象以告诉我它何时已保存到数据库:

domainObj.bind('saved', function() {
    map[domainObj.Id] = 'new foo!'
})
对于新对象,
Id
字段为空,在保存到数据库之前不会填充

这就是我的问题所在。对于新对象,查找“
map[domainObj.Id]
”失败,因为对象的标识在保存后已更改

在这样的身份映射中使用对象的最佳方式是什么

约束条件

  • 我使用的语言不允许对象作为映射[JavaScript]中的键
  • 保存新对象时,必须在服务器上生成
    Id
    字段

  • 更新

    谢谢你的反馈。我真的希望以与实体相同的方式映射值对象:仅仅因为值对象尚未保存,并不意味着它没有用于我的应用程序映射的值。事实上,我错误地理解了身份映射是什么(在重新阅读模式定义后,我发现我并没有真正使用身份映射)


    我提出的解决方案与Igor的答案非常直接:每个对象在实例化时都会被随机分配一个id。在对象所在的上下文的生命周期中,它是唯一的、不变的和不变的。对于数据库中的实体和新的实例化,它都存在。实体的调整是将其设置为与对象的真实标识相匹配。这使得调试更容易一些。这是我在映射中用作键的值。

    好吧,您必须找到一种方法来推迟将对象添加到映射中,直到它被保存并分配了一个ID。

    在对象获得标识之前,它只是一个值对象。只有在身份建立后,它才会成为一个实体

    在对象成为实体之前,您无法将其放入像您这样的身份映射中-这没有意义,因为您无法将其拉出(因为您没有找到它的唯一键)

    一种可能的办法:

  • 向类添加一个标志,该标志指示对象的状态(新建/保存)
  • 为这些对象实现一个临时(客户端)ID
  • 可选:
  • 单独的标识映射中保留“新”对象(如果无法避免客户端和服务器ID之间的ID冲突)
  • 相同的标识映射中保留“新”对象(如果可以避免客户端和服务器ID之间的ID冲突)
  • 保存对象后,将客户端ID替换为服务器ID,将状态设置为“已保存”,移动到主标识映射(如有必要)

  • 请参见此处的

    链接有何意义?我在FF,当我点击它,我得到一个404。然后我点击地址栏(仍然在404页面上)并按[Enter],它就工作了。谢谢。查看我更新的问题,了解我决定做什么。唯一的变化是答案的最后一部分:保存对象后,我不想用服务器ID替换客户机ID,因为映射在保存之外,并且不知道更新的ID(从“模式”的意义上说,它不是真正的身份映射;我错用了这个术语)。没有ID的实体仍然是实体。在实体中保留持久状态标志不是一个好主意,因为它不适用于持久无知的想法。@Paco:你说的可能是对的,但在你提供更好的替代解决方案之前,我认为我的建议仍然有效。至于没有ID的实体仍然是实体:从哲学的角度来说,这是正确的,但从实际编程的角度来说,情况并非如此。一个不给你姓名的人仍然是一个人,但你不会允许他在没有身份证明的情况下在投票申请中登记为选民。因此,在他的身份确定之前,他不是一个投票实体:)一个价值对象是不变的。不是每个没有id的对象都是值对象。Eric Evans在书中对这个问题做了很好的解释。你为什么要在identitymap中添加临时对象?@Paco:它不是一个身份映射。我误解了身份图的用途。我把问题的措辞留给了那些认为自己在使用身份地图而遇到这个问题的人。从你绝对正确的“身份地图”模式的意义上看,我的评论是对的。未从域检索到的值不属于映射。事实证明,我根本没有使用真正的标识映射,而是使用了一个映射,该映射恰好依赖于对象的“Id”字段来实现查找性能(相对于扫描集合)。