sObject Map Key Considerations

DEX455 - Apex sObject 集合完整指南

📄 第 201 页 🎬 视频课程

课程章节介绍

同学们,今天我们来聊一个在Apex中特别容易踩坑的小细节,就是拿sObject对象直接当Map的键来用。你可能觉得,把一个记录放进Map里,回头再拿同样的记录去取,肯定能取出来,对吧?但实际情况可能让你大跌眼镜。 我举个例子:假设你有一个联系人Contact对象,你创建它,没有Id,字段都是空的,然后你把它作为键,放了一个值进Map。接着,你可能把这个联系人插入到了数据库里,这下可好,系统自动给你的联系人填上了Id、CreatedDate这些字段。等你再拿着这个已经有Id的联系人去Map里找之前放进去的值,结果返回的是null,找不到了。明明还是那个对象,为什么找不到呢? 原因在于,Apex中的Map,当你用sObject当键的时候,它比较的不是对象的引用地址,而是对象身上所有字段的值。只要任何一个字段的值不一样,Map就认为这是两个不同的键。你最初放进去的那个对象,字段都是空的;插入数据库之后,Id、CreatedDate这些系统字段多出来了,相当于整个对象的字段值变了,所以Map就不认识它了。 这种情况在触发器里特别常见。比如你在一个before触发器里,从Trigger.New拿到了一批崭新的记录,这些记录都还没Id呢。你把它们当作键存进Map。等进了after触发器,同一条记录已经被提交,系统字段全填上了,这时候你再用它们去Map里取,一样取不出来。因为在Map眼里,before触发器和after触发器里的同一个sObject,字段值不一样,就不是同一个键。 所以我们的最佳实践是:如果需要拿记录做映射,尽量用记录的唯一标识,也就是Id字段,作为Map的键。比如说Map,而不是Map。用Id就不会受其他字段变化的影响,因为它一旦生成就稳定不变了。 总结一下,用sObject当Map键时要非常小心,因为键匹配是对比所有字段值,只要字段一变,键就失效。尤其是要注意系统字段自动填充的时机。安全起见,优先用Id做键。这个小细节记住了,以后可以少踩很多坑。 好,今天就讲到这儿,我们下个小节见。

关键词

Apex Salesforce Developer Guide