课程章节介绍
好,我们来看一个Apex开发中非常容易踩到的“坑”——关于事务里混合操作设置对象和非设置对象的问题。
你可能会问,什么是设置对象?就是那些和系统配置、用户权限相关的sObject,比如User、UserRole、Profile、PermissionSet等等。非设置对象就是我们平时处理业务的那些,比如Account、Contact、Opportunity。
在Apex里,如果你在一个事务中,既对设置对象做DML操作,又对非设置对象做DML操作,就可能会报错。官方说法是“某些设置对象上的TLR操作不能与非设置对象上的TLR混合”,TLR就是Trigger、Workflow、Process Builder这些自动化逻辑的统称。为啥会有这个限制?因为设置对象的变化会直接影响用户对记录的访问权限,Salesforce为了保证数据安全和权限一致性,就不允许在同一个事务里把这两类混在一起。
举个例子:你想在一个事务里,先更新一个Account,然后又去更新某个User的Role。这样可能会失败,因为更新了用户角色,权限就变了,之前那个Account的操作到底该不该允许呢?系统很难实时判断,干脆一刀切,不允许。
那遇到了该怎么办?有三种常用的解决方案:
第一种,用@future方法。把其中一类操作放到异步的@future方法里执行,这样它们就属于不同事务了,互不干扰。比如你把更新UserRole放到一个带@future的静态方法里,当前事务只处理Account,就不会冲突。
第二种,在测试类里,如果只是为了验证逻辑,可以用System.runAs()块来切换用户上下文。这样可以在不同权限下跑不同的DML,避开了混合事务的限制。
第三种,最根本的,就是设计上就把这两类操作拆到不同的事务里。比如用户点击按钮触发一个操作,你可以通过流程设计,先完成设置对象的更新,再通过另一个独立的进程去处理业务数据。
记住这个要点,你以后在写涉及权限和设置对象混合操作的代码时,就能提前规避这个报错了。这个限制不是Bug,而是Salesforce安全模型的一部分,理解原因之后,解决方法也很简单。
关键词
Apex
Salesforce
Developer Guide