如何修复 System.NullPointerException:尝试使用 Map<parentId, child> 在顶点 class 中 de-reference 空 object?
how to fix System.NullPointerException: Attempt to de-reference a null object in apex class using Map<parentId, child>?
获取行“taskObj.OwnerId = ConMap.get(ben.contact__c).contact__r.OwnerId;”中的错误因为 ownerid 字段正在联系。
Contact是parent的好处,这里我在start方法中得到了所有的好处。如果我使用 SET 时它有多个 child,我只想添加一次 contactid。我想使用地图,因为我需要从 contact object 获取联系人 OwnerId 字段,我在 start 方法的查询中获取它。如何使用地图访问 contact.ownerId 字段?下面是代码。
global Database.QueryLocator start(Database.BatchableContext bc) {
Query='select contact__r.ownerId, contact__c, Task_creation_date__c, Status__c, task_created__c, type__c from Benefit__c Where Task_creation_date__c= TODAY AND Status__c IN (\'Active\',\'Pending\') AND Task_created__c =FALSE AND Type__c!=\'Short Term Medical\'';
return Database.getQueryLocator(query);
}
global void execute(Database.BatchableContext bc, List<Benefit__c> scope){
// process each batch of records
List<Contact> contacts = new List<Contact>();
List<Task> TaskList = new List<Task>();
set<id> conset = New set<id>();
Map<id,benefit__c> ConMap = new map<id,Benefit__c>();
for (Benefit__c b : scope) {
conset.add(b.contact__c);
ConMap.put(b.contact__c, b);
b.task_created__c = TRUE;
}
system.debug('contact and its benefit------'+ConMap);
recordsProcessed = conset.size();
//List<Contact> tempList = new List<Contact>();
// tempList = [Select Id,OwnerId, firstname from Contact where Id IN:(conset)];
if(!ConMap.isEmpty())
{
for(Benefit__c ben : ConMap.values())
{
Task taskObj = new Task();
taskObj.OwnerId = ConMap.get(ben.contact__c).contact__r.OwnerId;
我想将联系人所有者 ID 填充为任务所有者 ID,但如何从地图访问它并在地图中保留唯一的联系人 ID?
我看到批量查询没有过滤条件'Contact__c != null'。因此,有可能其中一条福利记录在 'Contact__c' 字段中缺少值,而您无法在地图中找到它。您可以通过两种方式解决此问题:
- 如果您不关心这些记录,请将 'Contact__c != null' 添加到选择器查询。
(或)
检查 for 循环中的 'null' 值,如下所示:
if(!ConMap.isEmpty())
{
for(Benefit__c ben : ConMap.values())
{
if(String.isBlank(ben.Contact__c)){
/* continue;
or
throw exception()
*/
}
Task taskObj = new Task();
taskObj.OwnerId = ConMap.get(ben.contact__c).contact__r.OwnerId;
我重新编写了代码来解决这个问题并优化代码如下。
public with sharing class MyBatch implements Database.Batchable<AggregateResult>{
public Iterable<AggregateResult> start(Database.BatchableContext context)
{
return [
SELECT Contact__c, Contact__r.OwnerId owner FROM Benefit__c
WHERE Contact__c != null AND ...
GROUP BY Contact__c, Contact__r.OwnerId
];
}
public void execute(Database.BatchableContext context, List<AggregateResult> scope)
{
Set<Id> contactIds = new Set<Id>();
List<Task> tasks = new List<Task>();
for (AggregateResult aggregate : scope)
{
Id ownerId = (Id)aggregate.get('owner');
Id contactId = (Id)aggregate.get('Contact__c');
contactIds.add(contactId);
tasks.add(new Task(OwnerId=ownerId, /*other fields*/));
}
insert tasks;
List<Benefit__c> benefits = [
SELECT Id FROM Benefit__c WHERE Contact__c IN :contactIds
];
for (Benefit__c benefit : benefits)
benefit.Task_Created__c = true;
update benefits;
}
public void finish(Database.BatchableContext context) { /*additional logic*/ }}
获取行“taskObj.OwnerId = ConMap.get(ben.contact__c).contact__r.OwnerId;”中的错误因为 ownerid 字段正在联系。
Contact是parent的好处,这里我在start方法中得到了所有的好处。如果我使用 SET 时它有多个 child,我只想添加一次 contactid。我想使用地图,因为我需要从 contact object 获取联系人 OwnerId 字段,我在 start 方法的查询中获取它。如何使用地图访问 contact.ownerId 字段?下面是代码。
global Database.QueryLocator start(Database.BatchableContext bc) {
Query='select contact__r.ownerId, contact__c, Task_creation_date__c, Status__c, task_created__c, type__c from Benefit__c Where Task_creation_date__c= TODAY AND Status__c IN (\'Active\',\'Pending\') AND Task_created__c =FALSE AND Type__c!=\'Short Term Medical\'';
return Database.getQueryLocator(query);
}
global void execute(Database.BatchableContext bc, List<Benefit__c> scope){
// process each batch of records
List<Contact> contacts = new List<Contact>();
List<Task> TaskList = new List<Task>();
set<id> conset = New set<id>();
Map<id,benefit__c> ConMap = new map<id,Benefit__c>();
for (Benefit__c b : scope) {
conset.add(b.contact__c);
ConMap.put(b.contact__c, b);
b.task_created__c = TRUE;
}
system.debug('contact and its benefit------'+ConMap);
recordsProcessed = conset.size();
//List<Contact> tempList = new List<Contact>();
// tempList = [Select Id,OwnerId, firstname from Contact where Id IN:(conset)];
if(!ConMap.isEmpty())
{
for(Benefit__c ben : ConMap.values())
{
Task taskObj = new Task();
taskObj.OwnerId = ConMap.get(ben.contact__c).contact__r.OwnerId;
我想将联系人所有者 ID 填充为任务所有者 ID,但如何从地图访问它并在地图中保留唯一的联系人 ID?
我看到批量查询没有过滤条件'Contact__c != null'。因此,有可能其中一条福利记录在 'Contact__c' 字段中缺少值,而您无法在地图中找到它。您可以通过两种方式解决此问题:
- 如果您不关心这些记录,请将 'Contact__c != null' 添加到选择器查询。
(或)
检查 for 循环中的 'null' 值,如下所示:
if(!ConMap.isEmpty()) { for(Benefit__c ben : ConMap.values()) { if(String.isBlank(ben.Contact__c)){ /* continue; or throw exception() */ } Task taskObj = new Task(); taskObj.OwnerId = ConMap.get(ben.contact__c).contact__r.OwnerId;
我重新编写了代码来解决这个问题并优化代码如下。
public with sharing class MyBatch implements Database.Batchable<AggregateResult>{
public Iterable<AggregateResult> start(Database.BatchableContext context)
{
return [
SELECT Contact__c, Contact__r.OwnerId owner FROM Benefit__c
WHERE Contact__c != null AND ...
GROUP BY Contact__c, Contact__r.OwnerId
];
}
public void execute(Database.BatchableContext context, List<AggregateResult> scope)
{
Set<Id> contactIds = new Set<Id>();
List<Task> tasks = new List<Task>();
for (AggregateResult aggregate : scope)
{
Id ownerId = (Id)aggregate.get('owner');
Id contactId = (Id)aggregate.get('Contact__c');
contactIds.add(contactId);
tasks.add(new Task(OwnerId=ownerId, /*other fields*/));
}
insert tasks;
List<Benefit__c> benefits = [
SELECT Id FROM Benefit__c WHERE Contact__c IN :contactIds
];
for (Benefit__c benefit : benefits)
benefit.Task_Created__c = true;
update benefits;
}
public void finish(Database.BatchableContext context) { /*additional logic*/ }}