更新 Apex 触发器中的父对象字段
Update Parent Object Field in Apex Trigger
我有三个对象
1)Truck__c
2)Booking__C
3)Payment___C。
Truck 和 Booking 具有主从关系,其中 Truckk 是主从,Booking 是从属。
Booking 和 payment 有查找关系,其中 Booking 是父项,payment 是子项。
我想根据付款对象中 remainingAmount 字段中存在的值更新 Truck 中存在的 isBooked(checkbox) 字段。我在付款对象上添加了触发器,如下所示
trigger TestTrigger on Payment__c (after insert) {
if(Trigger.isAfter && Trigger.isUpdate){
for (Payment__c pay:Trigger.New)
{
payId.add(pay.id);
paidAmount =Integer.valueOf(pay.Paid_Amount__c);
}
Map <id,Booking__c> bookingMap = new Map <id,Booking__c> ();
for (Booking__c obj: [Select Id, Booking_ID__c from Booking__c where Booking_ID__c in:payId])
{
bookingMap.put(obj.Booking_ID__c, obj);
}
for(Booking__c objBooking:matchingIdsMap){
Truck__c truckObj = [Select id,Price__c from Truck__c where Truck__c.id = objBooking.Truck__c.id];
//Integer paidAmount = Payment__c.Paid_Amount__c;
Integer totalAmount = Integer.valueOf(truckObj.Price__c);
Integer remainingAmount = totalAmount-paidAmount;
If(remainingAmount == 0){
truckObj.Booked__c = true
}
update truckObj;
}
}
}
首先,我获取付款 ID,并基于此获取作为付款查找父项的预订对象。在此之后,我试图获取作为 Booking 主人的卡车对象。但我不知道如何在查询中查询此作为 where 子句给出错误
Truck__c truckObj = [Select id,Price__c from Truck__c where Truck__c.id = objBooking.Truck__c.id];
请注意卡车和付款之间没有直接关系
如何获取卡车对象
提前致谢
简短回答:在引用 parent 字段时,您应该使用 relationship name,因此 Truck__r
而不是 Truck__c
。
无论如何,这不是该代码的唯一问题。
长答案:
- 您的触发器位于
after insert
,但您检查更新后事件:if(Trigger.isAfter && Trigger.isUpdate)
。可能您想 运行 在插入后和更新后都触发此触发器。
- 您从未声明过您在第一个 for-loop 中使用的
payId
或 paidAmount
。无论如何 paidAmount
只会保留最后一个值,您可能不需要它。
[Select Id, Booking_ID__c from Booking__c where Booking_ID__c in:payId]
此查询应该 return 一个空列表,因为在 payId
中您存储了 Payment__c 的 ID,即 child Booking__c,而在第一个循环中,您应该存储 parents Booking__c 的 ID
[Select id,Price__c from Truck__c where Truck__c.id = objBooking.Truck__c.id]
这里没有理由写where Truck__c.id
应该就是WHERE Id = :objBooking.Truck__c
.
- 当心:将 SOQL 放入循环中,您将很容易遇到关于 SOQL 的 Governor Limit,这将引发
System.LimitException: Too many SOQL queries: 101
。
将 DML 放入循环中也是如此。
我假设查找字段的 API 名称与 parent object 相同,因此 Booking__c
字段存在于Payment__c
object 并且 Truck__c
存在于 Booking__c
object.
如果我对如何在 Truck object 上设置标志的逻辑正确,这应该是触发代码。
trigger TestTrigger on Payment__c (after insert, after update) {
if(Trigger.isAfter && (Trigger.isInsert || Trigger.isUpdate)) {
Map<Id, List<Payment__c>> mapBookingIdPaymentList = new Map<Id, List<Payment__c>>();
for (Payment__c pay : Trigger.New) {
List<Payment__c> paymentList = mapBookingIdPaymentList.get(pay.Booking__c);
if (paymentList == null) {
paymentList = new List<Payment__c>();
mapBookingIdPaymentList.put(pay.Booking__c, paymentList);
}
paymentList.add(pay);
}
Map<Id, Decimal> mapTruckPrice = new Map<Id, Decimal>();
Map<Id, Integer> mapTruckRemainingAmount = new Map<Id, Integer>();
for (Booking__c booking: [SELECT Id, Truck__c, Truck__r.Price__c FROM Booking__c WHERE Id IN :mapBookingIdPaymentList.keySet()]) {
mapTruckPrice.put(booking.Truck__c, booking.Truck__r.Price__c);
Integer sumOfRemainingAmount = mapTruckRemainingAmount.containsKey(booking.Truck__c) ? mapTruckRemainingAmount.get(booking.Truck__c) : 0;
for (Payment__c pay : mapBookingIdPaymentList.get(booking.Id)) {
sumOfRemainingAmount += pay.Paid_Amount__c != null ? pay.Paid_Amount__c.intValue() : 0;
}
mapTruckRemainingAmount.put(booking.Truck__c, sumOfRemainingAmount);
}
List<Truck__c> trucksToUpdate = new List<Truck__c>();
for (Id truckId : mapTruckPrice.keySet()) {
// There is no need to query a record just to update it if you already have its Id.
Truck__c truck = new Truck__c(Id = truckId);
truck.Booked__c = mapTruckPrice.get(truckId) - mapTruckRemainingAmount.get(truckId) == 0;
trucksToUpdate.add(truck);
}
update trucksToUpdate; // dml outside the loop
}
}
顺便说一下,您应该按照最佳实践将逻辑移至处理程序 class。
我有三个对象 1)Truck__c 2)Booking__C 3)Payment___C。 Truck 和 Booking 具有主从关系,其中 Truckk 是主从,Booking 是从属。 Booking 和 payment 有查找关系,其中 Booking 是父项,payment 是子项。
我想根据付款对象中 remainingAmount 字段中存在的值更新 Truck 中存在的 isBooked(checkbox) 字段。我在付款对象上添加了触发器,如下所示
trigger TestTrigger on Payment__c (after insert) {
if(Trigger.isAfter && Trigger.isUpdate){
for (Payment__c pay:Trigger.New)
{
payId.add(pay.id);
paidAmount =Integer.valueOf(pay.Paid_Amount__c);
}
Map <id,Booking__c> bookingMap = new Map <id,Booking__c> ();
for (Booking__c obj: [Select Id, Booking_ID__c from Booking__c where Booking_ID__c in:payId])
{
bookingMap.put(obj.Booking_ID__c, obj);
}
for(Booking__c objBooking:matchingIdsMap){
Truck__c truckObj = [Select id,Price__c from Truck__c where Truck__c.id = objBooking.Truck__c.id];
//Integer paidAmount = Payment__c.Paid_Amount__c;
Integer totalAmount = Integer.valueOf(truckObj.Price__c);
Integer remainingAmount = totalAmount-paidAmount;
If(remainingAmount == 0){
truckObj.Booked__c = true
}
update truckObj;
}
}
}
首先,我获取付款 ID,并基于此获取作为付款查找父项的预订对象。在此之后,我试图获取作为 Booking 主人的卡车对象。但我不知道如何在查询中查询此作为 where 子句给出错误
Truck__c truckObj = [Select id,Price__c from Truck__c where Truck__c.id = objBooking.Truck__c.id];
请注意卡车和付款之间没有直接关系
如何获取卡车对象 提前致谢
简短回答:在引用 parent 字段时,您应该使用 relationship name,因此 Truck__r
而不是 Truck__c
。
无论如何,这不是该代码的唯一问题。
长答案:
- 您的触发器位于
after insert
,但您检查更新后事件:if(Trigger.isAfter && Trigger.isUpdate)
。可能您想 运行 在插入后和更新后都触发此触发器。 - 您从未声明过您在第一个 for-loop 中使用的
payId
或paidAmount
。无论如何paidAmount
只会保留最后一个值,您可能不需要它。 [Select Id, Booking_ID__c from Booking__c where Booking_ID__c in:payId]
此查询应该 return 一个空列表,因为在payId
中您存储了 Payment__c 的 ID,即 child Booking__c,而在第一个循环中,您应该存储 parents Booking__c 的 ID
[Select id,Price__c from Truck__c where Truck__c.id = objBooking.Truck__c.id]
这里没有理由写where Truck__c.id
应该就是WHERE Id = :objBooking.Truck__c
.- 当心:将 SOQL 放入循环中,您将很容易遇到关于 SOQL 的 Governor Limit,这将引发
System.LimitException: Too many SOQL queries: 101
。 将 DML 放入循环中也是如此。
我假设查找字段的 API 名称与 parent object 相同,因此 Booking__c
字段存在于Payment__c
object 并且 Truck__c
存在于 Booking__c
object.
如果我对如何在 Truck object 上设置标志的逻辑正确,这应该是触发代码。
trigger TestTrigger on Payment__c (after insert, after update) {
if(Trigger.isAfter && (Trigger.isInsert || Trigger.isUpdate)) {
Map<Id, List<Payment__c>> mapBookingIdPaymentList = new Map<Id, List<Payment__c>>();
for (Payment__c pay : Trigger.New) {
List<Payment__c> paymentList = mapBookingIdPaymentList.get(pay.Booking__c);
if (paymentList == null) {
paymentList = new List<Payment__c>();
mapBookingIdPaymentList.put(pay.Booking__c, paymentList);
}
paymentList.add(pay);
}
Map<Id, Decimal> mapTruckPrice = new Map<Id, Decimal>();
Map<Id, Integer> mapTruckRemainingAmount = new Map<Id, Integer>();
for (Booking__c booking: [SELECT Id, Truck__c, Truck__r.Price__c FROM Booking__c WHERE Id IN :mapBookingIdPaymentList.keySet()]) {
mapTruckPrice.put(booking.Truck__c, booking.Truck__r.Price__c);
Integer sumOfRemainingAmount = mapTruckRemainingAmount.containsKey(booking.Truck__c) ? mapTruckRemainingAmount.get(booking.Truck__c) : 0;
for (Payment__c pay : mapBookingIdPaymentList.get(booking.Id)) {
sumOfRemainingAmount += pay.Paid_Amount__c != null ? pay.Paid_Amount__c.intValue() : 0;
}
mapTruckRemainingAmount.put(booking.Truck__c, sumOfRemainingAmount);
}
List<Truck__c> trucksToUpdate = new List<Truck__c>();
for (Id truckId : mapTruckPrice.keySet()) {
// There is no need to query a record just to update it if you already have its Id.
Truck__c truck = new Truck__c(Id = truckId);
truck.Booked__c = mapTruckPrice.get(truckId) - mapTruckRemainingAmount.get(truckId) == 0;
trucksToUpdate.add(truck);
}
update trucksToUpdate; // dml outside the loop
}
}
顺便说一下,您应该按照最佳实践将逻辑移至处理程序 class。