OrientDB勾點類似於資料庫術語中的觸發器,它在使用者應用程式中的每個CRUD操作之前和之後啟用內部事件。可以使用掛鉤編寫自定義驗證規則,強制執行安全性,或安排外部事件,例如針對關係DBMS進行複製。
OrientDB支援兩種勾點 -
動態勾點
動態勾點比Java勾點更靈活,因為它們可以在執行時更改,並且可以根據需要執行每個文件,但比Java勾點慢。
要對文件執行勾點,首先將類擴充套件OTriggered
基礎類別。 之後,為相應的事件定義一個自定義屬性。 以下是可用的事件。
onBeforeCreate
- 在建立新文件之前呼叫。onAfterCreate
- 建立新文件後呼叫。onBeforeRead
- 在讀取文件之前呼叫。onAfterRead
- 讀取文件後呼叫。onBeforeUpdate
- 在更新文件之前呼叫。onAfterUpdate
- 更新文件後呼叫。onBeforeDelete
- 在刪除文件之前呼叫。onAfterDelete
- 刪除文件後呼叫。動態掛鉤可以呼叫 -
類級別勾點
為與類相關的所有文件定義類級別勾點。 以下是一個範例,用於設定一個針對文件的類級別的勾點。
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
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程式碼。
注:將下載的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專家,所以希望本教學中包含的資訊能夠讓您領先一步,讓您對該技術感到滿意,從而使您能夠在需要時成功建立資料庫觸發器。