Apex 的 Trigger 类简介
Apex Triggers
Apex 触发器(Apex Triggers)是一种特殊的 Apex 类。它的主要作用是在一条记录被插入、修改、删除之前或之后自动执行一系列的操作。每一个 Trigger 类必须对应一种对象。
Trigger 的语法和普通的 Apex 类一样。
Salesforce 建议开发者在创建 Trigger 之前,考虑一下相同的操作可否通过 Salesforce 的设置界面中的功能完成,比如验证规则(Validation Rule)、工作流规则(Workflow Rule)等。如果可以,则优先使用它们。
Trigger 结构与触发事件
Trigger 的标准结构如下:
trigger Trigger名字 on 对象名字 (触发事件) {
// Do something
}
Trigger 类必须以关键字 “trigger” 开始,然后是此 Trigger 的名字。接下来是 “on” 关键字,然后是 Trigger 对应的对象的名字。对象名字后面的括号中写入触发 Trigger 的事件。
Trigger 的触发事件分为以下几种:
- before insert:插入数据之前
- before update:更新数据之前
- before delete:删除数据之前
- after insert:插入数据之后
- after update:更新数据之后
- after delete:删除数据之后
- after undelete:恢复数据之后
比如:
trigger HelloWorldTrigger on Account (before insert, before update) {
System.debug('Hello World!');
}
这个 Trigger 在每一个 Account 对象插入或更新之前执行。
如果执行了如下代码:
Account a = new Account(Name='test');
insert a;
a.Name = 'test2';
update a;
在这两个 DML 语句生效前,系统的日志中会添加 “Hello World!” 的记录。
Trigger 的预设变量
Trigger 类可以使用一些系统预设的变量,来辅助实现一些公共的操作。
Trigger.New 和 Trigger.Old
Trigger.New 和 Trigger.Old 是两个预定义变量,可以用于每一个 Trigger 类中。前者代表了即将被插入、更新的数据,后者代表了更新之前、删除之前的数据。它们可能包含一条数据,也可能包含一组数据,取决于触发 Trigger 时的状态。
要注意的是,Trigger.New 不存在于 delete 操作中,因为删除之后就没有数据了。而 Trigger.Old 不存在于 insert 操作中,因为插入数据之前是没有数据的。
在下面的代码中,我们可以为每一条即将被插入数据库的 Account 数据定义 Description 字段的值。
trigger HelloWorldTrigger on Account (before insert) {
for(Account acc : Trigger.New) {
acc.Description = 'New account desc';
}
}
通过这个 Trigger,当每一条 Account 数据被插入数据库之前,都会被定义 Description 字段的值。
布尔值变量
除了 Trigger.New 和 Trigger.Old,系统还提供了一系列的布尔值变量,用于标志 Trigger 或数据的状态。
最常用的有:
- isInsert:是否是 insert 操作
- isUpdate:是否是 update 操作
- isDelete:是否是 delete 操作
- isBefore:是否是操作之前
- isAfter:是否是操作之后
在下面的代码中,我们可以定义对于不同的操作和不同的时机,写入不同的日志记录。
trigger HelloWorldTrigger on Account (before insert, after insert, before delete) {
if(Trigger.isInsert) {
if(Trigger.isBefore) {
System.debug('This is before insert');
} else if(Trigger.isAfter) {
System.debug('This is after insert');
}
} else if(Trigger.isDelete) {
System.debug('This is delete');
}
}
Trigger 中的错误处理
在 Trigger 中,我们可以为进行操作的数据进行验证,类似于验证规则。如果遇到不符合条件的数据,可以通过 addError() 函数来将错误显示给用户,并记录日志。
在如下代码中,当一个“业务机会”对象被插入或更新之前,系统会检查“金额”字段的值是否不小于1000。如果“金额”的数值小于1000,该“业务机会”记录将不能被插入或更新。
错误信息的显示适用于前端和后端:
- 如果该记录是从用户页面修改的,则用户会看到错误信息
- 如果该记录是从 Apex 程序中被插入或修改,则错误信息会被记录在日志中
trigger OppyMaxAmountTrigger on Opportunity (before insert, before update) {
for(Opportunity opp : Trigger.New) {
if(opp.amount < 1000) {
opp.addError('Amount should not be less than 1000!');
}
}
}
最佳实践:批量处理数据
由于 Trigger 类是在数据被操作的时候自动执行,而 Salesforce 是运行在云端的平台,所以对于 Trigger 类的一个最佳实践是:尽量批量处理数据,而非对每条数据在 Trigger 中单独处理。
比如在普通的 Apex 类中,有一段代码要更新一组 Contact 数据:
update contactList;
而系统中需要一个 Trigger 类在每个 Contact 对象更新之前设定其 FirstName 的值。
如果在 Trigger 中每次只处理一条数据,比如:
trigger ContactRenameTrigger on Contact (before update) {
Contact c = Trigger.New[0];
c.FirstName = 'default first name';
}
那么在一组 Contact 数据要更新的情况下,该 Trigger 会被执行很多次,每条数据一次。
如果将 Trigger 改为处理所有数据,比如:
trigger ContactRenameTrigger on Contact (before update) {
for(Contact c : Trigger.New) {
c.FirstName = 'default first name';
}
}
那么 Trigger 只需要执行一次,就可以将要处理的一组 Contact 数据中每条数据都进行更新,提高了效率。
在 Trigger 中也可以执行 SOQL 查询和 DML 操作。这时也要尽量先准备好一组数据,然后执行一次 DML 操作,而非对每一条记录单独执行一次。
比如,在更新每个 Account 数据之后,都要插入一条 Opportunity 数据,那么可以在 Trigger 中先用 SOQL 查询提取出所有的 Account 数据,然后对于每一个 Account 数据新建一个 Opportunity 数据,再一次性将所有的 Opportunity 数据用 DML 语句插入数据库中。
trigger AddOpportunityTrigger on Account (after update) {
List<Opportunity> oppList = new List<Opportunity>();
List<Account> accList = [SELECT Id, Name FROM Account WHERE Id IN :Trigger.New];
for(Account a : accList) {
oppList.add(new Opportunity(Name=a.Name+' opp',
StageName='Prospecting',
CloseDate=System.today().addMonths(1),
AccountId=a.Id)
);
}
if(oppList.size() > 0) {
insert oppList;
}
}
在上面的代码中,只执行了一次 SOQL 和 DML 语句。
如果在 for 循环中用 SOQL 单独查询出每一条 Account 的数据,然后新建一个 Opportunity 数据,并用 DML 插入这一条数据,那么执行效率会大大降低。
Apex 的 Trigger 类简介的更多相关文章
- ImageView类简介
4.8 图片控件 本节将要介绍的是图片控件ImageView,首先对ImageView类进行简单介绍,然后通过一个案例来说明ImageView的用法. 4.8.1 ImageView类简介 Ima ...
- Spring Security——核心类简介——获得登录用户的相关信息
核心类简介 目录 1.1 Authentication 1.2 SecurityContextHolder 1.3 AuthenticationManager和Authenti ...
- DriverManager 驱动管理器类简介 JDBC简介(三)
驱动程序管理器是负责管理驱动程序的,驱动注册以后,会保存在DriverManager中的已注册列表中 后续的处理就可以对这个列表进行操作 简言之,驱动管理器,就是字面含义,主要负责就是管理 驱动 概述 ...
- Java基础-日期格式化DateFormat类简介
Java基础-日期格式化DateFormat类简介 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.DateFormat类概述 DateFormat 是日期/时间格式化子类的抽象 ...
- Java基础-StringBuffer类与StringBuilder类简介
Java基础-StringBuffer类与StringBuilder类简介 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.StringBuffer类 在学习过String类之后 ...
- 34、Collections工具类简介
Collections工具类简介 就像数组中的Arrays工具类一样,在集合里面也有跟Arrays类似的工具类Collections package com.sutaoyu.Collections; ...
- JAVA nio 2 和 Path 类简介
想要初步了解 NIO.2 API,也就是通常所说的“JSR203: More New I/O APIs for the Java Platform”,最好的切入点就是新的抽象类 java.nio.fi ...
- QT中QWidget类简介
一.详细描述 QWidget类是所有用户界面对象的基类.通俗的来讲,Qt基本上所有的UI类都是由QWidget继承出来的,而QWidget继承于QObject, 大家可以查阅Qt source 即可 ...
- Java并发包中CopyOnWrite容器相关类简介
简介: 本文是主要介绍,并发容器CopyOnWriteArrayList和CopyOnWriteArraySet(不含重复元素的并发容器)的基本原理和使用示例. 欢迎探讨,如有错误敬请指正 如需转载, ...
随机推荐
- .NET手记-定义类和接口的扩展方法
对于iOS开发者来说,使用扩展方法是家常便饭.因为有很多的类是有系统框架的定义的,我们不能修改或者不想修改他们的源码,但是我们又想要给他添加一些扩展方法来使用.这时定义扩展方法就是很有用的方式了,正如 ...
- Java运行环境(win10)
系统安装Java后,配置运行环境,我的系统是win10,之前随便装了,没想到最近执行javac命令报错,(网上找了一堆都没用)处理方式如下: 环境变量-新建:变量名:%JAVA_HOME% 变量值: ...
- 课程四(Convolutional Neural Networks),第四 周(Special applications: Face recognition & Neural style transfer) —— 3.Programming assignments:Face Recognition for the Happy House
Face Recognition for the Happy House Welcome to the first assignment of week 4! Here you will build ...
- Alienware 15 R3 装Ubuntu 和 win10 双系统
一.安装环境 Alienware 15 R3 win10 专业版64位 ubuntu16.04 二.软件下载 1.Ubuntu16.04 下载地址:https://www.ubuntu.com/dow ...
- shell脚本实现FTP自动上传文件
-----多个文件----- #!/bin/bash ftp -n<<! open 172.20.10.242 user logftp logftp binary cd /data/ftp ...
- mysql修改数据路径
步凑: 1.关闭mysql服务 [root@localhost /]# service mysqld stop 2.移动mysql文件夹到自定义的目录 [root@localhost /]# mv / ...
- MySQL百万级、千万级数据多表关联SQL语句调优
本文不涉及复杂的底层数据结构,通过explain解释SQL,并根据可能出现的情况,来做具体的优化,使百万级.千万级数据表关联查询第一页结果能在2秒内完成(真实业务告警系统优化结果).希望读者能够理解S ...
- 十余年软件开发经历,经验总结和程序一览(涉及Socket、WPF、vc++、CAD、图像、GIS)
前言 本文主要介绍我开发的几款软件产品,大概介绍一下功能.可以让读者了解本人的开发能力,所擅长的方面.有相关开发需求可以联系作者. 本人开发软件多年,从事的行业也多种多样:自然接触了不同的业务,开发了 ...
- Java并发编程笔记之ArrayBlockingQueue源码分析
JDK 中基于数组的阻塞队列 ArrayBlockingQueue 原理剖析,ArrayBlockingQueue 内部如何基于一把独占锁以及对应的两个条件变量实现出入队操作的线程安全? 首先我们先大 ...
- leetcode — reverse-nodes-in-k-group
/** * Source : https://oj.leetcode.com/problems/reverse-nodes-in-k-group/ * * Created by lverpeng on ...