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'開頭的類,並在建立記錄時設定CreatedDateUpdatedDate,並在每次記錄更新時設定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伺服器

建立一個以字母rt開頭的新類 -

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 
----+-----+------+----+-----------+-----------

即使您沒有指定為CreatedDateUpdatedDate設定值,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專家,所以希望本教學中包含的資訊能夠讓您領先一步,讓您對該技術感到滿意,從而使您能夠在需要時成功建立資料庫觸發器。