- OrientDB 教程
- OrientDB - 首页
- OrientDB - 概述
- OrientDB - 安装
- OrientDB - 基本概念
- OrientDB - 数据类型
- OrientDB - 控制台模式
- OrientDB 数据库命令
- OrientDB - 创建数据库
- OrientDB - 修改数据库
- OrientDB - 备份数据库
- OrientDB - 恢复数据库
- OrientDB - 连接数据库
- OrientDB - 断开数据库连接
- OrientDB - 数据库信息
- OrientDB - 列出数据库
- OrientDB - 冻结数据库
- OrientDB - 释放数据库
- OrientDB - 配置数据库
- OrientDB - 导出数据库
- OrientDB - 导入数据库
- OrientDB - 提交数据库
- OrientDB - 回滚数据库
- OrientDB - 优化数据库
- OrientDB - 删除数据库
- OrientDB 记录命令
- OrientDB - 插入记录
- OrientDB - 显示记录
- OrientDB - 加载记录
- OrientDB - 重新加载记录
- OrientDB - 导出记录
- OrientDB - 更新记录
- OrientDB - 清空记录
- OrientDB - 删除记录
- OrientDB 类命令
- OrientDB - 创建类
- OrientDB - 修改类
- OrientDB - 清空类
- OrientDB - 删除类
- OrientDB 集群命令
- OrientDB - 创建集群
- OrientDB - 修改集群
- OrientDB - 清空集群
- OrientDB - 删除集群
- OrientDB 属性命令
- OrientDB - 创建属性
- OrientDB - 修改属性
- OrientDB - 删除属性
- OrientDB 顶点命令
- OrientDB - 创建顶点
- OrientDB - 移动顶点
- OrientDB - 删除顶点
- OrientDB 边命令
- OrientDB - 创建边
- OrientDB - 更新边
- OrientDB - 删除边
- OrientDB 高级概念
- OrientDB - 函数
- OrientDB - 序列
- OrientDB - 索引
- OrientDB - 事务
- OrientDB - 钩子
- OrientDB - 缓存
- OrientDB - 日志
- OrientDB - 性能调优
- OrientDB - 升级
- OrientDB - 安全性
- OrientDB - Studio
- OrientDB 接口
- OrientDB - Java 接口
- OrientDB - Python 接口
- OrientDB 有用资源
- OrientDB - 快速指南
- OrientDB - 有用资源
- OrientDB - 讨论
OrientDB - 钩子
OrientDB 的钩子在数据库术语中就是触发器,它可以在用户应用程序中每个 CRUD 操作的前后触发内部事件。您可以使用钩子编写自定义验证规则,实施安全策略,或安排外部事件,例如与关系型数据库管理系统进行复制。
OrientDB 支持两种类型的钩子:
动态钩子 - 可以在类级别和/或文档级别构建的触发器。
Java(原生)钩子 - 使用 Java 类构建的触发器。
动态钩子
动态钩子比 Java 钩子更灵活,因为它们可以在运行时更改,并且可以根据需要在每个文档上运行,但速度比 Java 钩子慢。
要对您的文档执行钩子,首先允许您的类扩展OTriggered基类。之后,为感兴趣的事件定义一个自定义属性。以下是可用的事件。
onBeforeCreate - 在创建新文档之前调用。
onAfterCreate - 在创建新文档之后调用。
onBeforeRead - 在读取文档之前调用。
onAfterRead - 在读取文档之后调用。
onBeforeUpdate - 在更新文档之前调用。
onAfterUpdate - 在更新文档之后调用。
onBeforeDelete - 在删除文档之前调用。
onAfterDelete - 在删除文档之后调用。
动态钩子可以调用:
用 SQL、Javascript 或 OrientDB 和 JVM 支持的任何语言编写的函数。
Java 静态方法。
类级别钩子
类级别钩子是为所有与某个类相关的文档定义的。以下是一个设置在类级别针对 Invoice 文档执行钩子的示例。
CREATE CLASS Invoice EXTENDS OTriggered ALTER CLASS Invoice CUSTOM onAfterCreate = invoiceCreated
让我们在 Javascript 中创建函数invoiceCreated,它在服务器控制台中打印创建的发票编号。
CREATE FUNCTION invoiceCreated "print('\\nInvoice created: ' + doc.field ('number'));"
LANGUAGE Javascript
现在尝试通过创建一个新的Invoice文档来使用此钩子。
INSERT INTO Invoice CONTENT {number: 100, notes: 'This is a test}
如果此命令成功执行,您将获得以下输出。
Invoice created: 100
文档级别钩子
您可以仅针对一个或多个文档定义特定操作。为此,允许您的类扩展OTriggered类。
例如,让我们针对现有的 Profile 类执行一个 Javascript 函数作为触发器,该触发器针对所有属性 account = 'Premium' 的文档。该触发器将被调用以阻止删除文档。
ALTER CLASS Profile SUPERCLASS OTriggered UPDATE Profile SET onBeforeDelete = 'preventDeletion' WHERE account = 'Premium'
让我们创建preventDeletion() Javascript 函数。
CREATE FUNCTION preventDeletion "throw new java.lang.RuntimeException('Cannot
delete Premium profile ' + doc)" LANGUAGE Javascript
然后通过尝试删除“Premium”账户来测试此钩子。
DELETE FROM #12:1
java.lang.RuntimeException: Cannot delete Premium profile
profile#12:1{onBeforeDelete:preventDeletion,account:Premium,name:Jill} v-1
(<Unknown source>#2) in <Unknown source> at line number 2
JAVA 钩子
OrientDB 钩子(触发器)的一个常见用例是管理任何或所有类的创建日期和更新日期。例如,您可以在创建记录时设置CreatedDate字段,在更新记录时设置UpdatedDate字段,并且以一种方式实现逻辑,即在数据库层实现一次,以后在应用程序层不再需要担心它。
在创建之前,您需要通过访问以下链接下载orientdb-core.jar文件下载 OrientDB 核心。之后,将该 jar 文件复制到您要存储 Java 源文件的文件夹中。
创建钩子文件
创建一个名为HookTest.java的 Java 文件,它将使用 Java 语言测试钩子机制。
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;
import com.orientechnologies.orient.core.hook.ODocumentHookAbstract;
import com.orientechnologies.orient.core.hook.ORecordHook;
import com.orientechnologies.orient.core.hook.ORecordHookAbstract;
import com.orientechnologies.orient.core.db.ODatabaseLifecycleListener;
import com.orientechnologies.orient.core.db.ODatabase;
import com.orientechnologies.orient.core.record.ORecord;
import com.orientechnologies.orient.core.record.impl.ODocument;
public class HookTest extends ODocumentHookAbstract implements ORecordHook {
public HookTest() {
}
@Override
public DISTRIBUTED_EXECUTION_MODE getDistributedExecutionMode() {
return DISTRIBUTED_EXECUTION_MODE.BOTH;
}
public RESULT onRecordBeforeCreate( ODocument iDocument ) {
System.out.println("Ran create hook");
return ORecordHook.RESULT.RECORD_NOT_CHANGED;
}
public RESULT onRecordBeforeUpdate( ODocument iDocument ) {
System.out.println("Ran update hook");
return ORecordHook.RESULT.RECORD_NOT_CHANGED;
}
}
上面的示例代码在每次创建或更新该类的记录时打印相应的注释。
让我们再添加一个钩子文件setCreatedUpdatedDates.java,如下所示:
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;
import com.orientechnologies.orient.core.hook.ODocumentHookAbstract;
import com.orientechnologies.orient.core.hook.ORecordHook;
import com.orientechnologies.orient.core.hook.ORecordHookAbstract;
import com.orientechnologies.orient.core.db.ODatabaseLifecycleListener;
import com.orientechnologies.orient.core.db.ODatabase;
import com.orientechnologies.orient.core.record.ORecord;
import com.orientechnologies.orient.core.record.impl.ODocument;
public class setCreatedUpdatedDates extends ODocumentHookAbstract implements ORecordHook {
public setCreatedUpdatedDates() {
}
@Override
public DISTRIBUTED_EXECUTION_MODE getDistributedExecutionMode() {
return DISTRIBUTED_EXECUTION_MODE.BOTH;
}
public RESULT onRecordBeforeCreate( ODocument iDocument ) {
if ((iDocument.getClassName().charAt(0) == 't') || (iDocument.getClassName().charAt(0)=='r')) {
iDocument.field("CreatedDate", System.currentTimeMillis() / 1000l);
iDocument.field("UpdatedDate", System.currentTimeMillis() / 1000l);
return ORecordHook.RESULT.RECORD_CHANGED;
} else {
return ORecordHook.RESULT.RECORD_NOT_CHANGED;
}
}
public RESULT onRecordBeforeUpdate( ODocument iDocument ) {
if ((iDocument.getClassName().charAt(0) == 't') || (iDocument.getClassName().charAt(0)=='r')) {
iDocument.field("UpdatedDate", System.currentTimeMillis() / 1000l);
return ORecordHook.RESULT.RECORD_CHANGED;
} else {
return ORecordHook.RESULT.RECORD_NOT_CHANGED;
}
}
}
上面代码的作用是查找以字母“r”或“t”开头的任何类,并在记录创建时设置 CreatedDate 和 UpdatedDate,并在每次记录更新时仅设置 UpdatedDate。
编译 Java 钩子
使用以下命令编译 Java 代码。注意:将下载的 jar 文件和这些 Java 文件放在同一个文件夹中。
$ jar cf hooks-1.0-SNAPSHOT.jar *.java
将编译后的代码移动到 OrientDB 服务器可以找到的位置
您需要将生成的 .jar 文件复制到 OrientDB 服务器将查找它们的目录。这意味着 OrientDB 服务器根目录下的“./lib”文件夹将如下所示:
$ cp hooks-1.0-SNAPSHOT.jar "$ORIENTDB_HOME/lib"
在 OrientDB 服务器配置文件中启用测试钩子
编辑$ORIENTDB_HOME/config/orientdb-server-config.xml并在文件末尾附近添加以下部分。
<hooks>
<hook class = "HookTest" position = "REGULAR"/>
</hooks>
...
</orient-server>
重启 OrientDB 服务器
重新启动 OrientDB 服务器后,您在orientdb-server-config.xml中定义的钩子现在处于活动状态。启动一个 OrientDB 控制台,将其连接到您的数据库,然后运行以下命令:
INSERT INTO V SET ID = 1;
如果此命令成功执行,您将获得以下输出。
Ran create hook
现在运行以下命令:
UPDATE V SET ID = 2 WHERE ID = 1;
如果此命令成功执行,您将获得以下输出。
Ran update hook
在 OrientDB 服务器配置文件中启用真实钩子
编辑$ORIENTDB_HOME/config/orientdb-server-config.xml并将 hooks 部分更改如下:
<hooks>
<hook class="setCreatedUpdatedDates" position="REGULAR"/>
</hooks>
...
</orient-server>
重启 OrientDB 服务器
创建一个以字母“r”或“t”开头的新的类:
CREATE CLASS tTest EXTENDS V;
现在插入一条记录:
INSERT INTO tTest SET ID = 1 SELECT FROM tTest
如果此命令成功执行,您将获得以下输出。
----+-----+------+----+-----------+----------- # |@RID |@CLASS|ID |CreatedDate|UpdatedDate ----+-----+------+----+-----------+----------- 0 |#19:0|tTest |1 |1427597275 |1427597275 ----+-----+------+----+-----------+-----------
即使您没有指定要为CreatedDate和UpdatedDate设置的值,OrientDB 也已自动为您设置了这些字段。
接下来,您需要使用以下命令更新记录:
UPDATE tTest SET ID = 2 WHERE ID = 1; SELECT FROM tTest;
如果此命令成功执行,您将获得以下输出。
----+-----+------+----+-----------+----------- # |@RID |@CLASS|ID |CreatedDate|UpdatedDate ----+-----+------+----+-----------+----------- 0 |#19:0|tTest |2 |1427597275 |1427597306 ----+-----+------+----+-----------+-----------
您可以看到 OrientDB 已更改了UpdatedDate,但保持CreatedDate不变。
OrientDB Java 钩子可以成为一个非常有价值的工具,有助于自动化您原本必须在应用程序代码中执行的工作。由于许多 DBA 并不总是 Java 专家,希望本教程中包含的信息能够让您有一个良好的开端,并让您对该技术感到满意,从而使您能够在需要时成功创建数据库触发器。