异常或者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 /** 121 * 针对必填字段获取友好的message 122 * @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] 123 * @param sObjectName : sObject的API Name 124 * @return : 友好消息 eg : Required fields are missing: Company Name (field label name) 125 */ 126 private static String getUserFriendlyMessage4RequiredField(String msg,String sObjectName){ 127 String errorMessage = msg; 128 if(!errorMessage.contains('first error:')) { 129 return errorMessage; 130 } 131 Integer pointer; 132 String fieldName; 133 //获取first error 以后的message信息 134 pointer = errorMessage.indexOf('first error:') + 12; 135 errorMessage = errorMessage.mid(pointer, errorMessage.length()); 136 if(pointer > -1){ 137 pointer = errorMessage.indexOf(',') + 1; 138 errorMessage = errorMessage.mid(pointer, errorMessage.length()); 139 } 140 141 pointer = errorMessage.indexOf(']:'); 142 if(pointer > -1){ 143 errorMessage = errorMessage.mid(0, pointer + 1); 144 } 145 fieldName = errorMessage.mid(errorMessage.indexOf('[') + 1,errorMessage.indexOf(']')-errorMessage.indexOf('[')-1).trim(); 146 if(fieldName != null) { 147 Schema.DescribeFieldResult fieldResult = getSObjectFieldDescribeResult(sObjectName,fieldName); 148 if(fieldResult != null) { 149 fieldName = fieldResult.getLabel(); 150 } 151 } 152 pointer = errorMessage.indexOf('['); 153 if(pointer > -1){ 154 errorMessage = errorMessage.mid(0, pointer); 155 } 156 errorMessage += fieldName; 157 return errorMessage; 158 } 159 160 /* 161 * 通过sObject名称以及field名称获取field相关describe result信息 162 * @param sObjectName object的api name 163 * @param fieldName field的api name 164 * @return 此field的describe result 165 */ 166 private static Schema.DescribeFieldResult getSObjectFieldDescribeResult(String sObjectName,String fieldName) { 167 ListsObjectResultList = Schema.describeSObjects(new String[]{sObjectName}); 168 if(sObjectResultList == null || sObjectResultList.size() == 0) { 169 return null; 170 } else { 171 Schema.DescribeSObjectResult sObjectResult = sObjectResultList.get(0); 172 Map maps = sObjectResult.fields.getMap(); 173 Schema.SObjectField sObjectField = maps.get(fieldName); 174 if(sObjectField == null) { 175 return null; 176 } else { 177 Schema.DescribeFieldResult fieldDescribeResult = sObjectField.getDescribe(); 178 return fieldDescribeResult; 179 } 180 } 181 } 182 183 }
使用演示:
1.Unique字段插入重复
2.必填字段为空
3.Validation Rule未通过
总结:此篇主要封装简单的异常的友好显示。当前很多常量都放在了程序里,建议放在custom label中,然后对相关进行translate,这样可以保证国际化使用,否则现在language为英文可以,中文使用会有问题,有用到的可以自行优化。