OrientDB鉤子(觸發器)
OrientDB鉤子類似於數據庫術語中的觸發器,它在用戶應用程序中的每個CRUD操作之前和之後啓用內部事件。可以使用掛鉤編寫自定義驗證規則,強制執行安全性,或安排外部事件,例如針對關係DBMS進行復制。
OrientDB支持兩種鉤子 -
- 動態鉤子 - 觸發器,可以在類級別和/或文檔級別構建。
- Java(Native)鉤子 - 觸發器,可以使用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}
如果此命令成功執行,您將獲得以下輸出。
Invoice created: 100
文檔級別鉤子
只能針對一個或多個文檔定義特殊操作。 要做到這一點,創建的類需要擴展OTriggered
類。
例如,針對所有具有屬性account ='Premium'
的文檔,現有的Profile
類執行觸發器,如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
然後通過嘗試刪除「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 Hooks(觸發器)的一個常見用例是管理任何或所有類的創建和更新日期。 例如,無論何時創建一條記錄,都可以設置一個CreatedDate
字段,並且每當記錄更新時設置一個UpdatedDate
字段,並以您在數據庫層實現邏輯一次的方式執行,而不必再次擔心應用程序層。
創建完成後,您需要通過訪問以下鏈接下載OrientDB核心來orientdb-core.jar
文件。 然後將該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
並在文件末尾添加以下部分。
<orient-server>
<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服務器配置文件中啓用Real Hook
編輯$ORIENTDB_HOME/config/orientdb-server-config.xml
並按如下方式更改鉤子部分 -
<orient-server>
<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專家,所以希望本教程中包含的信息能夠讓您領先一步,讓您對該技術感到滿意,從而使您能夠在需要時成功創建數據庫觸發器。