Salesforce使用truncate清空数据库

如果想快速的清空MySQL中的表,可以使用Truncate命令。
Truncate能够快速的,对数据进行无差别的清空。

在Mysql中使用truncate的语法是
TRUNCATE TABLE [Table Name];

在Salesforce中同样提供了Truncate功能。不过只是提供一个按钮,并不提供任何代码及API调用Truncate的方式。
所以正确的应用场景,应该只是用来快速的清空临时数据或者测试数据。毕竟,无论使用Batch还是dataloader来删除全部数据都要花费大量的时间。

在Salesforce中想要看到Truncate按钮的话,需要达成如下条件,参考官方文档:

  1. Profile -> Administrative Permissions -> Customize Application -> True
  2. User Interface -> Setup -> Enable Custom Object Truncate -> True

然后在到Custom Object的详细画面,就能看到在Edit,Delete按钮旁边Truncate按钮出现了。

不过,并不是任何Object任何情况都能进行Truncate,有如下要求,参考官方文档:

  1. 不能被别的Object Lookup,或者处在Master-Detail中的Master地位。
  2. 不能被Report Snapshot参照。
  3. 不能有自定义字段是Index或者是External ID。
  4. 不能开启了skinny table。(关于Skinny Table的事情会另外写一篇)。

为什么会有如上的限制,显而易见,与Salesforce中Truncate的动作有关。
在Salesforce中,虽然Truncate功能与MySQL类似,用来清空表中的数据,但是会导致Custom Object的Id Prefix产生变化。所以所有通过三位Id Prefix引用此Custom Object的功能都会失效。如果Apex/VF/Button中有直接使用3位Id Prefix进行判断的逻辑,就会受到影响。

除此之外,另一点与MySQL不用的是,如果有一个自增字段。MySQL在Truncate后,会重置自增字段的计数器。而Salesforce则不会。没错,虽然ID变了,但自增字段会接着数并不会重新回到起始值。

匿名块中SavePoint的使用技巧

经常要使用匿名块验证代码片段的可用性,尤其是在写测试类的时候。一个很长的测试类,一口气写完,再逐一排查问题是很低效的。

但是,使用匿名块执行代码片段的话,插入数据或者修改数据的动作就会对数据库造成实际的影响。这个时候,我们就可以使用SavePoint来避免这个问题。

如下

Savepoint sp = Database.setSavepoint();

// Place your code here

Database.rollback(sp);

这样,如果DML代码成功了,也不会对数据库造成任何影响。

关于SavePoint和Rollback,参照官方文档

Salesforce中的Apex Class Security设定问题

在我以往的印象中,给Profile设定VF和Apex Class的访问权限,都是需要什么就加什么。

比如新建了一个VF叫PageA, 又新建了一个Controller叫ControllerA,然后新建了一个被Controller调用的工具类ToolA。
那么,在此Profile中,PageA,ControllerA和ToolA通通都要加到Profile的访问权限里。

如果只添加了PageA,按理说应该是无法正常执行才对。

但通过实践,发现就算只添加了PageA的权限,整个功能仍然能正常运行。与之前的印象不符。

所以去查了文档,发现官方给出的解释是这样的:

Permission for an Apex class is checked only at the top level. For example, if class A calls class B, and a user profile has access only to class A but not class B, the user can still execute the code in class A. Likewise, if a Visualforce page uses a custom component with an associated controller, security is only checked for the controller associated with the page. The controller associated with the custom component executes regardless of permissions.

就是说如果代码之间存在着依赖链,那么权限判断中,只关注最顶层的那个代码。按照这个逻辑下来,只要拥有了PageA的权限,因为PageA与ControllerA的依赖关系,就自动获取了ControllerA的访问权限,同理ToolA。

知其然,不知其所以然还是不对的。

Salesforce如何取得Guest User的Debug Log

// Update4 2018/04/10

Salesforce这次不仅吃书。。。连设定都吃回去了。。。
这篇文章不用看了,以后再也不用设Cookie了。一切又回到了最初的样子。
官方文档

从Winter’17开始,Guest User的Debug Log不再能通过正常渠道直接获取了。这给我们做Wechat集成的小伙伴们造成了很大的困扰。
虽然说官方文档中,介绍了在Chrome下使用插件添加Cookie的方法来激活Guest User的Debug log,但微信里是没法修改Cookie的。
不过官方提到了可以通过各种代码添加Cookie的Sample Code,尤其是Javascript,可以放到被访问的页面上。
代码只有简简单单的一句

document.cookie ="debug_logs=debug_logs;domain=.force.com";

在修改了Page之后,兴冲冲的打开了微信进行测试,发现并没有卵用。
然后切回浏览器,通过浏览器访问发现,这段Js代码加入的Cookie值与我之前用插件添加进去的值并完全不一致。
不一致的属性是“Path”,由于我的Salesforce Site是设定了Path的,所以Js代码生成的Cookie的Path也跟着变成了我设定的Path。而我用插件加入的Cookie的Path属性默认为“/”。
好,那么我们修改一下这句Js

document.cookie ="debug_logs=debug_logs;domain=.force.com;path=/";

修改完之后再试,问题解决,Debug Log乖乖出来了。
打完收工。

// Update 1

微信内置浏览器是可以使用Cookie的,不过要慎重,因为微信的内置浏览器对于Cookie的处理策略与桌面浏览器不是很一致,并且每个版本都有变动。所以不应该过度依赖于微信内置浏览器的Cookie。

// Update 2

微信的内置浏览器为X5内核,所以行为和渲染等都与Webkit内核有出入。慎重!!
另,Spring’17 开始进入倒计时的时候,发现前文提到的官方文档不见了!!但是此方法仍然有效!!到底发生了什么!!

// Update 3
对于Salesforce官方不断吃书的行为表示不满与谴责(Knowledge文章被取消了)。
然并卵,已经不是第一次吃书了,所以想参考官方文档的同学看这里

Salesforce不登录调用Webservice的方法

Salesforce中提供了WebService的调用方式,在系统内部使用的时候,比如通过VF上的JS,或者通过标准页面上的按钮进行调用,可以方便的实现很多功能。
同时,Salesforce中的WebService可以也以rest方式提供给第三方系统进行可控的数据交互。
但是,鉴于Salesforce的License价格虚高,并且有些第三方,例如微信后台是无法进行身份认证的时候,通过public site开放WebSerivce用rest方式调用就非常有必要了。

首先,要在Webservice的首行添加@RestResource(urlMapping=’/{your name}/*’)
之后定义好@HttpGet方法或者@HttpPost方法。

将WebService类及相关类加到Site的可访问Apex Class列表里。
准备完毕后确认site有没有设定Path。
如果是sandbox的话
https://{prefix}.{sandbox instance Name}.force.com/{path}/services/apexrest/{Name Space}/{webservice urlMapping Name}/{your paramater}
如果是Production的话,
https://{prefix}.secure.force.com/{path}/services/apexrest/{Name Space}/{webservice urlMapping Name}/{your paramater}

尤其是Name Space,曾经难倒无数英雄汉。

Salesforce删除数据时出现Insufficient privileges的可能原因

遇到一个诡异的情况,用户通过界面删除一条自定义Object的数据的时候出现了Insufficient privileges。
按理说,如果用户的Profile没有此Object的删除权限的话,应该连删除按钮都看不到才对。

事情有蹊跷。首先检查了Profile,增删改查都有,但是没有Motify All和View All。
那么排除了Profile的嫌疑。
接下来查看Role。发现此用户的Role在role hierarchy中已经是比较高的位置了。
然后检查Sharing Rule。发现此Object的基本Sharing设定已经改成了Private,并且启用了role hierarchy。
那么问题就应该出在这里了。
去查看用户无法删除的那条数据,果然Owner不是用户本人,且Owner的Role与此用户同级。

在Salesforce中,如果Object的全局Sharing Rule为Private,那么除非用户的Profile是System Admin或者拥有Motify All权限,否则当用户想删除的数据的Owner为别人且Role为同级或者更高级的话,就会出现权限不足的问题。

告知用户,想删除此数据的话,请先把Owner改成自己,然后再删除。问题解决。

参考来自官网的信息

Task中的字段TaskSubType在ApexClass中不可见问题

在Task上有一个标准字段叫做TaskSubType,是一个Picklist。在属性页面无法看到与选择任何属性。也无法更改Picklist里的值,虽然里面有内置三个值。

某一天,我试图在Task的trigger里判断字段TaskSubType的值,在保存代码时报错,错误内容为“Error: Compile Error: Invalid field TaskSubtype for SObject Task”。

我用查询工具查询该字段,正常。
我用匿名块访问该字段,正常。

奇了个怪了。

使用查询工具查看该字段,有create-able,filter-able,nillable,restricted picklist,sort-able,没有update-able。不过应该不影响这里。也查看了FLS,也没有问题。

好,耐心查看Task的文档,发现此字段原名ActivitySubType,是在Winter’16加入Salesforce的。再回头一看ApexClass,原来用的是API 30。

果断改成API 36。保存正常。

这个就类似于Java的JDK,在JDK1.8加入的新特性,在JDK1.4是肯定无法使用的。
较早前创建的Apex Class或者Visualforce Page一定要注意API版本问题。

Salesforce的Trust终于改版了

trust site是由Salesforce提供,用来监控所有服务与实例状态的网站。

经典应用场景是,发现实例变得很慢,然后打开trust,哦。。。发生了性能降低。

新版trust也提供了新版API,可以获得相关实例的JSON串,自己定时获取,自己解析,可以实现自动提醒,自动警报。

API地址 https://api.status.salesforce.com/v1/instances/{你的实例名}/status

所有接口的说明 https://api.status.salesforce.com/v1/docs/

Salesfroce更新了Summer 16′ 版本的ForceIDE v37.0

官网地址:https://developer.salesforce.com/page/Force.com_IDE_Installation
更新日志:https://developer.salesforce.com/page/Force.com_IDE_Release_Notes

我在Eclipse Neon上已经成功更新。
本次更新的最大变更是。。。。更改了插件安装地址。没错。
还有提供了Lightning单独的开发组件。

另外,值得一提的是,启用了Java早就有的Open Type功能。

重点来了,打断点! Debug调式!没错!像个堂堂正正的Java程序员那样!
不过我还没试验这个新功能,之后会更新。