OrientDB 钩子
OrientDB
Hooks 只不过是数据库术语中的触发器,它在用户应用程序中的每个 CRUD 操作之前和之后启用内部事件。您可以使用钩子编写自定义验证规则、强制实施安全性或安排外部事件,例如针对关系 DBMS 进行复制。
OrientDB 支持两种钩子-
Dynamic Hook-触发器,可以在类级别和/或文档级别构建。
Java (Native) Hook-触发器,可以使用 Java 类构建。
动态钩子
动态钩子比 Java 钩子更灵活,因为它们可以在运行时更改,并且可以在需要时按文档运行,但比 Java 钩子慢。
要对您的文档执行挂钩,首先允许您的类扩展
OTriggered 基类。稍后,为感兴趣的事件定义自定义属性。以下是可用的事件。
onBeforeCreate-在创建新文档之前调用。
onAfterCreate-在创建新文档后调用。
onBeforeRead-在读取文档之前调用。
onAfterRead-在阅读文档后调用。
onBeforeUpdate-在更新文档之前之前调用。
onAfterUpdate-在更新文档后调用。
onBeforeDelete-在删除文档之前调用。
onAfterDelete-在删除文档后调用。
动态钩子可以调用-
函数,用 SQL、Javascript 或 OrientDB 和 JVM 支持的任何语言编写。
Java 静态方法。
类级别挂钩
为与类相关的所有文档定义了类级挂钩。以下是设置一个钩子的示例,该钩子在类级别对发票文档起作用。
CREATE class Invoice extends OTriggered
ALTER class Invoice CUSTOM onAfterCreate = invoiceCreated
让我们在 Javascript 中创建函数
invoiceCreated,在服务器控制台中打印创建的发票编号。
CREATE FUNCTION invoiceCreated "print('\\nInvoice created: ' + doc.field ('number'));"
LANGUAGE Javascript
现在尝试创建一个新的
发票文档。
INSERT INTO Invoice CONTENT {number: 100, notes: 'this is a test}
如果这条命令执行成功,你会得到如下输出。
文档级挂钩
您只能针对一个或多个文档定义特殊操作。为此,请允许您的类扩展
OTriggered 类。
例如,让我们针对现有的 Profile 类为所有属性 account = 'Premium' 的文档执行一个触发器,作为 Javascript 函数。将调用触发器以防止删除文档。
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
然后通过尝试删除"高级"帐户来测试挂钩。
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 Hooks(触发器)的一个常见用例是管理任何或所有类的创建和更新日期。例如,您可以在创建记录时设置
CreatedDate 字段并在更新记录时设置
UpdatedDate 字段,并以实现逻辑的方式执行此操作一次在数据库层,再也不用担心在应用层。
在创建之前,您必须通过访问以下链接下载
orientdb-core.jar 文件 下载OrientDB core。然后将该 jar 文件复制到要存储 Java 源文件的文件夹中。
创建挂钩文件
创建一个名为
HookTest.java的Java文件,将使用Java语言测试Hook机制。
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;
如果这条命令执行成功,你会得到如下输出。
现在运行以下命令-
UPDATE V SET ID = 2 WHERE ID = 1;
如果这条命令执行成功,你会得到如下输出。
在 OrientDB 服务器配置文件中启用 Real Hook
编辑
$ORIENTDB_HOME/config/orientdb-server-config.xml 并更改钩子部分如下-
<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 Hooks 是一个非常有价值的工具,可以帮助您自动执行原本必须在应用程序代码中执行的工作。由于许多 DBA 并不总是 Java 专家,因此希望本教程中包含的信息能够让您有一个良好的开端,让您对这项技术感到满意,使您能够在需要时成功创建数据库触发器。