1. Обзор

OrientDB — это технология базы данных Multi-Model NoSQL с открытым исходным кодом, предназначенная для работы с моделями Graph, Document, Key-Value, GeoSpatial и Reactive при управлении запросами с синтаксисом SQL.

В этой статье мы рассмотрим настройку и использование API OrientDB Java.

2. Установка

Во-первых, нам нужно установить бинарный пакет.

Давайте загрузим последнюю стабильную версию OrientDB (2.2.x на момент написания этой статьи).

Во-вторых, нам нужно разархивировать его и переместить его содержимое в удобный каталог (используя ORIENTDB_HOME). Не забудьте добавить папку bin в переменные среды для удобного использования в командной строке.

Наконец, нам нужно отредактировать файл orientdb.sh, расположенный в $ORIENTDB_HOME/bin, заполнив местоположение (ORIENTDB_HOME) каталога OrientDB вместо ORIENTDB_DIR, а также системного пользователя, которого мы хотели бы использовать вместо USER_YOU_WANT_ORIENTDB_RUN_WITH.

Теперь у нас есть полностью работающая OrientDB. Мы можем использовать сценарий \u003coption\u003e orientdb.sh с параметрами:

start: для запуска состояния сервера: для проверки состояния stop: для остановки сервера

    Обратите внимание, что для запуска и остановки требуется пароль пользователя (тот, который мы установили в файле orientdb.sh).

Как только сервер будет запущен, он займет порт 2480. Поэтому мы можем получить к нему локальный доступ, используя этот URL:

Более подробную информацию об установке вручную можно найти здесь.

Примечание: для OrientDB требуется Java версии 1.7 или выше.

Предыдущие версии доступны здесь.

3. Настройка OrientDB Java API

Чтобы подсчитать всех авторов, нам просто нужно предоставить класс и экземпляр базы данных без необходимости писать SQL-запрос:

The OrientDB allows Java developers to work with three different APIs such as:

  • Graph API – graph databases
  • Document API – document-oriented databases
  • Object API – objects that are bound directly to OrientDB Document

We can use all those types within a single codebase just by integrating and using OrientDB.

Let’s have a look at some available jars we can include in the classpath of the project:

  • orientdb-core-*.jar: brings the core library
  • blueprints-core-*.jar: to bring the adapters core components
  • orientdb-graphdb-*.jar: gives the Graph database API
  • orientdb-object-*.jar: furnishes the Object database API
  • orientdb-distributed-*.jar: provides the distributed database plugin to work with a server cluster
  • orientdb-tools-*.jar: hands over the console command
  • orientdb-client-*.jar: provides the remote client
  • orientdb-enterprise-*.jar: enables the protocol and network classes shared by the client and server

The two last ones are required only if we’re managing our data on a remote server.

Let’s start with a Maven project and use the following dependencies:

<dependency>
    <groupId>com.orientechnologies</groupId>
    <artifactId>orientdb-core</artifactId>
    <version>2.2.31</version>
</dependency>
<dependency>
    <groupId>com.orientechnologies</groupId>
    <artifactId>orientdb-graphdb</artifactId>
    <version>2.2.31</version>
</dependency>
<dependency>
    <groupId>com.orientechnologies</groupId>
    <artifactId>orientdb-object</artifactId>
    <version>2.2.31</version>
</dependency>
<dependency>
    <groupId>com.tinkerpop.blueprints</groupId>
    <artifactId>blueprints-core</artifactId>
    <version>2.6.0</version>
</dependency>

Please check the Maven Central repository for the latest versions of OrientDB’s Core, GraphDB, Object APIs and the Blueprints-Core.

4. Usage

The OrientDB is using the TinkerPop Blueprints implementation for working with graphs.

TinkerPop is a Graph Computing Framework providing many ways of building graph databases, where each of them has its implementations:

Moreover, OrientDB allows to work with the three kinds of Schemas regardless the type of API:

  • Schema-Full – strict mode is enabled, so all the fields are specified during class creation
  • Schema-Less – classes are created with no specific property, so we can add them as we want; it’s the default mode
  • Schema-Hybrid – it’s the mix of schema-full and schema-less where we can create a class with pre-defined fields but let the record to define other custom ones

4.1. Graph API

Since this is a graph-based database, data is represented as a network containing Vertices (nodes) interconnected by Edges (arcs).

As a first step, let’s use the UI to create a Graph database called BaeldungDB with a user admin and password admin.

As we see in the subsequent image, the graph has been selected as database type, so consequently its data will be accessible in the GRAPH Tab:

Let’s now connect to the desired database, knowing that the ORIENTDB_HOME is an environment variable that corresponds to the installation folder of OrientDB:

@BeforeClass
public static void setup() {
    String orientDBFolder = System.getenv("ORIENTDB_HOME");
    graph = new OrientGraphNoTx("plocal:" + orientDBFolder + 
      "/databases/BaeldungDB", "admin", "admin");
}

Let’s initiate the Article, Author, and Editor classes – while showing how to add validation to their fields:

@BeforeClass
public static void init() {
    graph.createVertexType("Article");

    OrientVertexType writerType
      = graph.createVertexType("Writer");
    writerType.setStrictMode(true);
    writerType.createProperty("firstName", OType.STRING);
    // ...

    OrientVertexType authorType 
      = graph.createVertexType("Author", "Writer");
    authorType.createProperty("level", OType.INTEGER).setMax("3");

    OrientVertexType editorType
      = graph.createVertexType("Editor", "Writer");
    editorType.createProperty("level", OType.INTEGER).setMin("3");

    Vertex vEditor = graph.addVertex("class:Editor");
    vEditor.setProperty("firstName", "Maxim");
    // ...

    Vertex vAuthor = graph.addVertex("class:Author");
    vAuthor.setProperty("firstName", "Jerome");
    // ...

    Vertex vArticle = graph.addVertex("class:Article");
    vArticle.setProperty("title", "Introduction to ...");
    // ...

    graph.addEdge(null, vAuthor, vEditor, "has");
    graph.addEdge(null, vAuthor, vArticle, "wrote");
}

In the code snippet above, we made a simple representation of our simple database where:

  • Article is the schema-less class that contains articles
  • Writer is a schema-full super-class that holds necessary writer information
  • Writer is a sub-type of Author that holds its details
  • Editor is a schema-less sub-type of Writer that holds editor details
  • lastName field hasn’t been filled in the saved author but still appears on the following graph
  • we have a relation between all classes: an Author can write Article and needs to have an Editor
  • Vertex represents an entity with some fields
  • Edge is an entity that links two Vertices

Please note that by trying to add another property to an object of a full class we’ll end up with the OValidationException.

After connecting to our database using OrientDB studio, we’ll see the graph representation of our data:

Let’s see how to have the number of all records (vertices) of the database:

long size = graph.countVertices();

Now, let’s show just the number of Writer (Author & Editor) objects:

@Test
public void givenBaeldungDB_checkWeHaveTwoWriters() {
    long size = graph.countVertices("Writer");

    assertEquals(2, size);
}

In the next step, we can find all Writer‘s data, using the following statement:

Iterable<Vertex> writers = graph.getVerticesOfClass("Writer");

Finally, let’s query for all Editor‘s with level 7; here we only have one that matches:

@Test
public void givenBaeldungDB_getEditorWithLevelSeven() {
    String onlyEditor = "";
    for(Vertex v : graph.getVertices("Editor.level", 7)) {
        onlyEditor = v.getProperty("firstName").toString();
    }

    assertEquals("Maxim", onlyEditor);
}

The class name is always specified to look for a specific vertice when requesting. We can find more details here.

4.2. Document API

Next option is to use the OrientDB’s Document model. This exposes data manipulation via a simple record with information stored in fields where the type could be text, picture or a binary form.

Let’s use the UI again to create a database named BaeldungDBTwo, but now with a document as type:

Note: likewise this API also can be used either in schema-full, schema-less or schema-hybrid mode.

The database connection remains straightforward as we just need to instantiate an ODatabaseDocumentTx object, provide the database URL and the database user’s credentials:

@BeforeClass
public static void setup() {
    String orientDBFolder = System.getenv("ORIENTDB_HOME");
    db = new ODatabaseDocumentTx("plocal:" 
      + orientDBFolder + "/databases/BaeldungDBTwo")
      .open("admin", "admin");
}

Let’s start with saving a simple document that holds an Author information.

Here we can see that the class has been automatically created:

@Test
public void givenDB_whenSavingDocument_thenClassIsAutoCreated() {
    ODocument doc = new ODocument("Author");
    doc.field("name", "Paul");
    doc.save();

    assertEquals("Author", doc.getSchemaClass().getName());
}

Accordingly, to count the number of Authors, we can use:

long size = db.countClass("Author");

Let’s query documents again using a field value, to search for the Author‘s objects with level 7:

@Test
public void givenDB_whenSavingAuthors_thenWeGetOnesWithLevelSeven() {
    for (ODocument author : db.browseClass("Author")) author.delete();

    ODocument authorOne = new ODocument("Author");
    authorOne.field("firstName", "Leo");
    authorOne.field("level", 7);
    authorOne.save();

    ODocument authorTwo = new ODocument("Author");
    authorTwo.field("firstName", "Lucien");
    authorTwo.field("level", 9);
    authorTwo.save();

    List<ODocument> result = db.query(
      new OSQLSynchQuery<ODocument>("select * from Author where level = 7"));

    assertEquals(1, result.size());
}

Likewise, to delete all the records of Author class, we can use:

for (ODocument author : db.browseClass("Author")) {
    author.delete();
}

On the OrientDB studio’s BROWSE Tab we can make a query to get all our Author’s objects:

4.3. Object API

OrientDB doesn’t have the object type of database. Thus, the Object API is relying on a Document database.

In Object API type, all other concepts remain the same with only one addition – binding to POJO.

Let’s start by connecting to the BaeldungDBThree by using the OObjectDatabaseTx class:

@BeforeClass
public static void setup() {
    String orientDBFolder = System.getenv("ORIENTDB_HOME");
    db = new OObjectDatabaseTx("plocal:" 
      + orientDBFolder + "/databases/BaeldungDBThree")
      .open("admin", "admin");
}

Next, by assuming that the Author is the POJO used to hold an Author data, we need to register it:

db.getEntityManager().registerEntityClass(Author.class);

Author has getters and setters for the following fields:

  • firstName
  • lastName
  • level

Let’s create an Author with multi-line instructions if we acknowledged a no-arg constructor:

Author author = db.newInstance(Author.class);
author.setFirstName("Luke");
author.setLastName("Sky");
author.setLevel(9);
db.save(author);

On the other hand, if we’ve another constructor that takes the firstName, lastName, and level of the Author respectively, the instantiation is just one line:

Author author = db.newInstance(Author.class, "Luke", "Sky", 9);
db.save(author);

The following lines are using to browse and delete all the records of Author class:

for (Author author : db.browseClass(Author.class)) {
    db.delete(author);
}

Аналогичным образом мы запрашиваем авторов с уровнем 7 примерно так:

long authorsCount = db.countClass(Author.class);

Наконец, это официальное руководство, в котором представлены некоторые расширенные возможности использования Object API.

@Test
public void givenDB_whenSavingAuthors_thenWeGetOnesWithLevelSeven() {
    for (Author author : db.browseClass(Author.class)) {
        db.delete(author);
    }

    Author authorOne 
      = db.newInstance(Author.class, "Leo", "Marta", 7);
    db.save(authorOne);

    Author authorTwo
      = db.newInstance(Author.class, "Lucien", "Aurelien", 9);
    db.save(authorTwo);

    List<Author> result
      = db.query(new OSQLSynchQuery<Author>(
      "select * from Author where level = 7"));

    assertEquals(1, result.size());
}

5. Заключение

В этой статье мы рассмотрели, как использовать OrientDB в качестве системы управления базами данных с ее Java API. Мы также узнали, как добавить проверку полей и написать несколько простых запросов.

Как всегда, исходный код этой статьи можно найти на GitHub.

«