异常或者error code汇总:https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_calls_concepts_core_data_objects.htm

做项目的时候有很多异常是我们经常遇到的:

  1.空指针异常;

  2.死锁或者超时;

  3.级联删除时无级联表操作权限导致删除失败;

  4.一次请求查询超过50000条数据;

  5.查询时偏移量超过2000;

  6.不满足Validation Rule条件;

  7.必填字段为空;

  8.unique字段记录添加重复。

上述问题很多可以封装公共方法来捕获异常并且返回友好的提示信息,免得将异常直接抛出,导致用户一头雾水。

此篇针对常见异常进行最基本的封装,方便后期项目有类似需求可以直接使用。

ErrorHelper:此类封装的getUserFriendlyMessage方法用于当程序操作出现异常时,可以返回友好的错误提示信息,第一个参数是errormessage,即error.getMessage(),第二个参数为sObject的API Name。

  1. global with sharing class ErrorHelper {
  2. private static final String NULL_POINTER_EXCEPTION = '空指针错误';
  3. private static final String RECORD_ALREADY_INPROCESS = '记录已经被锁定';
  4. private static final String RECORD_OVER_LIMIT = '查询最多只能50000条,请输入搜索条件重新搜索';
  5. private static final String RECORD_OFFSET_OVER_LIMIT = '数据最多只能查询当前检索条件前2000条,请更改检索条件重试';
  6. private static final String RECORD_ALREADY_IN_PROCESS = '当前记录已经在流程中,如有问题,请与管理员联系';
  7. public static String getUserFriendlyMessage(String msg,String sObjectName) {
  8. String errorMessage;
  9. //空指针错误:System.NullPointerException: Attempt to de-reference a null object
  10. if(msg.contains('NullPointerException')){
  11. errorMessage = NULL_POINTER_EXCEPTION;
  12. }
  13. //死锁或者超时
  14. else if(msg.contains('UNABLE_TO_LOCK')){
  15. errorMessage = RECORD_ALREADY_INPROCESS;
  16. }
  17. //级联删除,没有当前表或者关联表权限导致的错误
  18. else if(msg.contains('DELETE_REQUIRED_ON_CASCADE')) {
  19.  
  20. }
  21. //查询50001
  22. else if(msg.contains('Too many query rows')) {
  23. errorMessage = RECORD_OVER_LIMIT;
  24. }
  25. //offset 超过2000
  26. else if(msg.contains('Maximum SOQL offset allowed is 2000')) {
  27. errorMessage = RECORD_OFFSET_OVER_LIMIT;
  28. }
  29. //当前记录已经在审批流中
  30. else if(msg.contains('ALREADY_IN_PROCESS')) {
  31. errorMessage = RECORD_ALREADY_IN_PROCESS;
  32. }
  33. //Validation Rule失败
  34. //eg: Update failed. First exception on row 0 with id a052800000BvtqEAAR; first error: FIELD_CUSTOM_VALIDATION_EXCEPTION, 商品价格不能为空且必须大于0.: [GoodsPrice__c]
  35. else if (msg.contains('FIELD_CUSTOM_VALIDATION_EXCEPTION')){
  36. errorMessage = getUserFriendlyMessage4ValidationException(msg,sObjectName);
  37. }
  38. //必填字段
  39. //eg:Insert failed. First exception on row 0; first error: REQUIRED_FIELD_MISSING, Required fields are missing: [Company_Name__c]: [Company_Name__c]
  40. else if(msg.contains('REQUIRED_FIELD_MISSING')){
  41. errorMessage = getUserFriendlyMessage4RequiredField(msg,sObjectName);
  42. }
  43. //对于unique的字段进行相同值插入会报此种错误:System.DmlException: Insert failed. First exception on row 0; first error: DUPLICATE_VALUE, duplicate value found: Company_Code_Unique__c duplicates value on record with id: a032800000KOlEr: []
  44.  
  45. else if(msg.contains('DUPLICATE_VALUE')) {
  46. errorMessage = getUserFriendlyMessage4DuplicateValue(msg,sObjectName);
  47. }
  48. return errorMessage;
  49. }
  50.  
  51. /**
  52. *针对unique字段添加重复值的异常获取友好的message
  53. *@param msg : 异常信息 eg : System.DmlException: Insert failed. First exception on row 0; first error: DUPLICATE_VALUE, duplicate value found: Company_Code_Unique__c duplicates value on record with id: a032800000KOlEr: []
  54. *@param sObjectName : sObject的API Name
  55. *@return
  56. */
  57. private static String getUserFriendlyMessage4DuplicateValue(String msg,String sObjectName) {
  58. String errorMessage = msg;
  59. Integer pointer;
  60. String fieldName;
  61. if(!msg.contains('DUPLICATE_VALUE')) {
  62. return errorMessage;
  63. }
  64. pointer = errorMessage.indexOf('DUPLICATE_VALUE') + 16;
  65. if(pointer > -1) {
  66. errorMessage = errorMessage.mid(pointer, errorMessage.length());
  67. }
  68. pointer = errorMessage.indexOf('duplicates');
  69. if(pointer > -1) {
  70. errorMessage = errorMessage.mid(0,pointer);
  71. }
  72. pointer = errorMessage.indexOf(':') + 1;
  73. if(pointer > -1) {
  74. fieldName = errorMessage.mid(pointer,errorMessage.length()).trim();
  75. Schema.DescribeFieldResult fieldResult = getSObjectFieldDescribeResult(sObjectName,fieldName);
  76. if(fieldResult != null) {
  77. fieldName = fieldResult.getLabel();
  78. }
  79. }
  80. errorMessage = errorMessage.mid(0,pointer) + fieldName;
  81. return errorMessage;
  82. }
  83.  
  84. /**
  85. *针对Validation Rule的异常获取友好的message
  86. *@param msg : 异常消息 eg: Update failed. First exception on row 0 with id a052800000BvtqEAAR; first error: FIELD_CUSTOM_VALIDATION_EXCEPTION, 商品价格不能为空且必须大于0.: [GoodsPrice__c]
  87. *@param sObjectName : sObject的API Name
  88. *@return 返回有问题的field labe + : + error message (eg : GoodsPrice : 商品价格不能为空且必须大于0.)
  89. */
  90. private static String getUserFriendlyMessage4ValidationException(String msg,String sObjectName){
  91. String errorMessage = msg;
  92. Integer pointer;
  93. String fieldName;
  94. if (msg.contains('FIELD_CUSTOM_VALIDATION_EXCEPTION')){
  95. pointer = errorMessage.indexOf('FIELD_CUSTOM_VALIDATION_EXCEPTION,') + 34;
  96. errorMessage = errorMessage.mid(pointer, errorMessage.length());
  97. } else {
  98. return msg;
  99. }
  100. pointer = errorMessage.indexOf('\n');
  101. if(pointer > -1){
  102. errorMessage = errorMessage.mid(0, pointer);
  103. }
  104. pointer = errorMessage.indexOf(':');
  105. if(pointer > -1){
  106. //去除error message中的 []
  107. fieldName = errorMessage.mid(pointer + 1,errorMessage.length()-1).remove('[').remove(']').trim();
  108. errorMessage = errorMessage.mid(0, pointer);
  109. }
  110. if(fieldName != null) {
  111. Schema.DescribeFieldResult fieldDescribeResult = getSObjectFieldDescribeResult(sObjectName,fieldName);
  112. if(fieldDescribeResult != null) {
  113. errorMessage = fieldDescribeResult.getLabel() + ' : ' + errorMessage;
  114. }
  115. }
  116. return errorMessage;
  117. }
  118.  
  119. /**
  120. * 针对必填字段获取友好的message
  121. * @param msg : 异常消息 eg: Insert failed. First exception on row 0; first error: REQUIRED_FIELD_MISSING, Required fields are missing: [Company_Name__c]: [Company_Name__c]
  122. * @param sObjectName : sObject的API Name
  123. * @return : 友好消息 eg : Required fields are missing: Company Name (field label name)
  124. */
  125. private static String getUserFriendlyMessage4RequiredField(String msg,String sObjectName){
  126. String errorMessage = msg;
  127. if(!errorMessage.contains('first error:')) {
  128. return errorMessage;
  129. }
  130. Integer pointer;
  131. String fieldName;
  132. //获取first error 以后的message信息
  133. pointer = errorMessage.indexOf('first error:') + 12;
  134. errorMessage = errorMessage.mid(pointer, errorMessage.length());
  135. if(pointer > -1){
  136. pointer = errorMessage.indexOf(',') + 1;
  137. errorMessage = errorMessage.mid(pointer, errorMessage.length());
  138. }
  139.  
  140. pointer = errorMessage.indexOf(']:');
  141. if(pointer > -1){
  142. errorMessage = errorMessage.mid(0, pointer + 1);
  143. }
  144. fieldName = errorMessage.mid(errorMessage.indexOf('[') + 1,errorMessage.indexOf(']')-errorMessage.indexOf('[')-1).trim();
  145. if(fieldName != null) {
  146. Schema.DescribeFieldResult fieldResult = getSObjectFieldDescribeResult(sObjectName,fieldName);
  147. if(fieldResult != null) {
  148. fieldName = fieldResult.getLabel();
  149. }
  150. }
  151. pointer = errorMessage.indexOf('[');
  152. if(pointer > -1){
  153. errorMessage = errorMessage.mid(0, pointer);
  154. }
  155. errorMessage += fieldName;
  156. return errorMessage;
  157. }
  158.  
  159. /*
  160. * 通过sObject名称以及field名称获取field相关describe result信息
  161. * @param sObjectName object的api name
  162. * @param fieldName field的api name
  163. * @return 此field的describe result
  164. */
  165. private static Schema.DescribeFieldResult getSObjectFieldDescribeResult(String sObjectName,String fieldName) {
  166. List<Schema.DescribeSObjectResult> sObjectResultList = Schema.describeSObjects(new String[]{sObjectName});
  167. if(sObjectResultList == null || sObjectResultList.size() == 0) {
  168. return null;
  169. } else {
  170. Schema.DescribeSObjectResult sObjectResult = sObjectResultList.get(0);
  171. Map<String,SObjectField> maps = sObjectResult.fields.getMap();
  172. Schema.SObjectField sObjectField = maps.get(fieldName);
  173. if(sObjectField == null) {
  174. return null;
  175. } else {
  176. Schema.DescribeFieldResult fieldDescribeResult = sObjectField.getDescribe();
  177. return fieldDescribeResult;
  178. }
  179. }
  180. }
  181.  
  182. }

使用演示:

1.Unique字段插入重复

2.必填字段为空

3.Validation Rule未通过

总结:此篇主要封装简单的异常的友好显示。当前很多常量都放在了程序里,建议放在custom label中,然后对相关进行translate,这样可以保证国际化使用,否则现在language为英文可以,中文使用会有问题,有用到的可以自行优化。

salesforce 零基础学习(五十四)常见异常友好消息提示的更多相关文章

  1. salesforce 零基础学习(十六)Validation Rules & Date/time

    上一篇介绍的内容为Formula,其中的Date/time部分未指出,此篇主要介绍Date/time部分以及Validation rules. 本篇参考PDF: Date/time:https://r ...

  2. salesforce 零基础学习(十九)Permission sets 讲解及设置

    Permission sets以及Profile是常见的设置访问权限的方式. Profile规则为'who see what'.通过Profile可以将一类的用户设置相同的访问权限.对于有着相同Pro ...

  3. salesforce 零基础学习(十八)WorkFlow介绍及用法

    说起workflow大家肯定都不陌生,这里简单介绍一下salesforce中什么情况下使用workflow. 当你分配许多任务,定期发送电子邮件,记录修改时,可以通过自动配置workflow来完成以上 ...

  4. salesforce零基础学习(九十四)classic下pagelayout引入的vf page弹出内容更新此page layout

    我们在classic环境中,有时针对page layout不能实现的地方,可以引入 一个vf page去增强标准的 page layout 功能,有时可能要求这个 vf page的部分修改需要更新此 ...

  5. salesforce 零基础学习(五十二)Trigger使用篇(二)

    第十七篇的Trigger用法为通过Handler方式实现Trigger的封装,此种好处是一个Handler对应一个sObject,使本该在Trigger中写的代码分到Handler中,代码更加清晰. ...

  6. salesforce零基础学习(八十)使用autoComplete 输入内容自动联想结果以及去重实现

    项目中,我们有时候会需要实现自动联想功能,比如我们想输入用户或者联系人名称,去联想出系统中有的相关的用户和联系人,当点击以后获取相关的邮箱或者其他信息等等.这种情况下可以使用jquery ui中的au ...

  7. salesforce零基础学习(八十九)使用 input type=file 以及RemoteAction方式上传附件

    在classic环境中,salesforce提供了<apex:inputFile>标签用来实现附件的上传以及内容获取.salesforce 零基础学习(二十四)解析csv格式内容中有类似的 ...

  8. salesforce零基础学习(一百零五)Change Data Capture

    本篇参考: https://developer.salesforce.com/docs/atlas.en-us.232.0.api_streaming.meta/api_streaming/using ...

  9. salesforce零基础学习(一百一十)list button实现的一些有趣事情

    本篇参考: salesforce零基础学习(九十五)lightning out https://developer.salesforce.com/docs/component-library/docu ...

随机推荐

  1. CMS模板应用调研问卷

    截止目前,已经有数十家网站与我们合作,进行了MIP化改造,在搜索结果页也能看到"闪电标"的出现.除了改造方面的问题,MIP项目组被问到最多的就是:我用了wordpress,我用了织 ...

  2. CRC、反码求和校验 原理分析

    3月份开始从客户端转后台,算是幸运的进入全栈工程师的修炼阶段.这段时间一边是老项目的客户端加服务器两边的维护和交接,一边是新项目加加加班赶工,期间最长经历了连续工作三天只睡了四五个小时的煎熬,人生也算 ...

  3. iOS可视化动态绘制八种排序过程

    前面几篇博客都是关于排序的,在之前陆陆续续发布的博客中,我们先后介绍了冒泡排序.选择排序.插入排序.希尔排序.堆排序.归并排序以及快速排序.俗话说的好,做事儿要善始善终,本篇博客就算是对之前那几篇博客 ...

  4. nginx的使用

    1.nginx的下载 解压后文件目录: 2.nginx的常用命令 nginx -s stop 强制关闭  nginx -s quit 安全关闭  nginx -s reload 改变配置文件的时候,重 ...

  5. [APUE]文件和目录(下)

    一.mkdir和rmdir函数 #include <sys/types.h> #include <sys/stat.h> int mkdir(const char *pathn ...

  6. windows环境redis主从安装部署

    准备工作 下载windows环境redis,我下载的是2.4.5,解压,拷贝一主(master)两从(slaveof).主机端口使用6379,两从的端口分别为6380和6381, 我本地索性用6379 ...

  7. C语言中如何判断文件是否存在

    方法一:access函数判断文件夹或者文件是否存在 函数原型: int access(const char *filename, int mode); 所属头文件:io.h filename:可以填写 ...

  8. 著名ERP厂商的SSO单点登录解决方案介绍一

          SSO英文全称Single Sign On,单点登录.SSO是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统.它包括可以将这次主要的登录映射到其他应用中用于同一个用户 ...

  9. Postman - 功能强大的 API 接口请求调试和管理工具

    Postman 是一款功能强大的的 Chrome 应用,可以便捷的调试接口.前端开发人员在开发或者调试 Web 程序的时候是需要一些方法来跟踪网页请求的,用户可以使用一些网络的监视工具比如著名的 Fi ...

  10. iOS之开发中一些相关的路径以及获取路径的方法

    模拟器的位置: /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs ...