Polymorphic Relationships in SOQL

DEX455 - Apex SOQL 与 SOSL 查询完全指南

📄 第 189 页 🎬 视频课程

课程章节介绍

好,同学们,我们来看看一个非常实用的概念,叫“多态关系”。听起来有点拗口,但其实很简单。 想象一下,Salesforce里有些字段特别灵活,它能引用好几种不同类型的对象。最经典的例子就是“任务”里的那个“谁”字段。你创建任务时,既可以关联到一个联系人,也可以关联到一个潜在客户,也就是Lead。它可以同时是这两种类型之一,这种关系就是多态关系。 那么在实际开发中,我们怎么处理这种灵活的关系呢?因为不同对象能访问的字段是不一样的,比如联系人有姓名,潜在客户有公司名。所以,Salesforce给我们提供了三种好用的方法,像工具箱一样,你根据需要来挑。 第一招,在查询里直接用类型来过滤。比如你写SOQL的时候,可以加一个条件:`WHERE Who.Type = 'Contact'`,这样就能只查出关联到联系人的任务了。Type就像一个内置的特殊字段,能帮你快速筛出想要的那种对象。 第二招,如果你一次查询想同时拿出不同类型里的不同字段,那就用到`TYPEOF`了。在`SELECT`里面,你可以这么写:`TYPEOF Who WHEN Contact THEN FirstName, LastName WHEN Lead THEN Company END`。翻译一下就是:如果这个“谁”是联系人,就给我返回名和姓;如果是潜在客户,就返回公司名。这样一条查询就能把两种对象的专属信息都取出来,非常方便。 第三招,是在Apex代码运行的时候,用`instanceof`来判断手里的记录到底是什么类型。比如你从查询里拿到了任务记录,它里面的“谁”字段是一个SObject,但你不知道具体是联系人还是潜在客户。这时候你可以写: ``` if (task.Who instanceof Contact) { Contact con = (Contact)task.Who; System.debug(con.FirstName); } else if (task.Who instanceof Lead) { Lead ld = (Lead)task.Who; System.debug(ld.Company); } ``` 像这样先判断,再强制转换,就能安全地访问专有字段了。 那这里有个重点得注意一下:在你拿到这个多态关系的SObject,想要把它传给另一个方法去处理的时候,千万别直接把它当通用SObject传过去就完事了。因为那个方法可能不认识这个通用对象里藏着什么具体类型。所以,你必须先把它赋值给一个明确类型的变量,比如转换成`Contact`或`Lead`,然后再传递,这样后面的代码才能正常使用。 我们用个完整的例子来串一遍吧,就是一个自定义对象“商品__c”。这个对象有一个“Owner”所有者字段,它也是多态的,既可以是用户,也可以是一个队列(也就是Group类型)。 好,那如果要查询那些所有者是用户类型的“商品__c”记录,我们就可以用第一招,写:`SELECT Id, Name FROM 商品__c WHERE Owner.Type = 'User'`。 如果想要一条查询同时拿到用户所有者的邮箱,以及队列所有者的名称,就在`SELECT`里用第二招`TYPEOF`:`SELECT TYPEOF Owner WHEN User THEN Email WHEN Group THEN Name END FROM 商品__c`。 拿到数据后,在代码里处理时,我现在不知道这个Owner到底是User还是Group,用第三招: ``` SObject ownerObj = 商品.Owner; if (ownerObj instanceof User) { User ownerUser = (User) ownerObj; // 现在就可以安全使用 ownerUser.Email 了 } else if (ownerObj instanceof Group) { Group ownerGroup = (Group) ownerObj; // 可以处理 ownerGroup.Name } ``` 然后把 ownerUser 或 ownerGroup 传给别的方法,就一清二楚了。 所以,多态关系就是这么灵活又有章法。记住这三招,过滤、查询专属字段、运行时判断,再配合正确的类型转换,你就能轻松驾驭它了。

关键词

Apex Salesforce Developer Guide