A Guide to Hibernate OGM – Hibernate OGM指南

最后修改: 2018年 12月 20日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In this tutorial, we’ll go through the basics of Hibernate Object/Grid Mapper (OGM).

在本教程中,我们将了解Hibernate Object/Grid Mapper(OGM)的基本知识。

Hibernate OGM provides Java Persistence API (JPA) support for NoSQL datastores. NoSQL is an umbrella term covering a wide variety of data storage. For example, this includes key-value, document, column-oriented and graph-oriented datastores.

Hibernate OGM为NoSQL数据存储提供Java Persistence API(JPA)支持。NoSQL是一个涵盖各种数据存储的总括术语。例如,这包括键值、文档、面向列和面向图的数据存储。

2. The Architecture of Hibernate OGM

2.Hibernate OGM的架构

Hibernate traditionally offers an Object Relational Mapping (ORM) engine for relational databases. Hibernate OGM engine extends its functionality to support NoSQL datastores. The primary benefit of using it is the consistency of the JPA interface across relational and NoSQL datastores.

Hibernate 传统上为关系型数据库提供一个对象关系映射(ORM)引擎Hibernate OGM 引擎扩展了其功能,以支持 NoSQL 数据集。使用它的主要好处是跨关系型和 NoSQL 数据集的 JPA 接口的一致性。

Hibernate OGM is able to provide abstraction over a number of NoSQL datastores because of two key interfaces, DatastoreProvider and GridDialect. Therefore, each new NoSQL datastore that it supports comes with an implementation of these interfaces.

Hibernate OGM能够提供对许多NoSQL数据存储的抽象,因为有两个关键的接口,DatastoreProviderGridDialect。因此,它所支持的每个新的NoSQL数据存储都带有这些接口的实现。

As of today, it does not support all NoSQL datastores, but it is capable of working with many of them like Infinispan and Ehcache (key-value), MongoDB and CouchDB (document), and Neo4j (graph).

截至目前,它并不支持所有的NoSQL数据存储,但它能够与许多数据存储一起工作,如Infinispan和Ehcache(键值),MongoDB和CouchDB(文档),以及Neo4j(图)。

It also fully supports transactions and can work with standard JTA providers. Firstly, this can be provided through the Jakarta EE container without any explicit configuration. Moreover, we can use a standalone JTA transaction manager like Narayana in the Java SE environment.

它还完全支持事务,并且可以与标准的JTA提供者一起工作。首先,这可以通过Jakarta EE容器提供,而无需任何显式配置。此外,我们可以在 Java SE 环境中使用独立的 JTA 事务管理器,如 Narayana。

3. Setup

3.设置

For this tutorial, we’ll use Maven to pull the required dependencies to work with Hibernate OGM. We’ll also use MongoDB.

在本教程中,我们将使用Maven来获取所需的依赖项,以便与Hibernate OGM一起工作。我们还将使用MongoDB>。

To clarify, let’s see how to set them up for the tutorial.

为了说明问题,让我们看看如何在教程中设置它们。

3.1. Maven Dependencies

3.1.Maven的依赖性

Let’s see the dependencies required to work with Hibernate OGM and MongoDB:

让我们看看与Hibernate OGM和MongoDB合作所需的依赖性。

<dependency>
    <groupId>org.hibernate.ogm</groupId>
    <artifactId>hibernate-ogm-mongodb</artifactId>
    <version>5.4.0.Final</version>
</dependency>
<dependency>
    <groupId>org.jboss.narayana.jta</groupId>
    <artifactId>narayana-jta</artifactId>
    <version>5.9.2.Final</version>
</dependency>

Here we’re pulling required dependencies through Maven:

在这里,我们通过Maven拉取所需的依赖。

3.2. Persistence Unit

3.2.持久性单位

We’ll also have to define datastore details in the Hibernate persistance.xml:

我们还必须在Hibernate的persistance.xml定义数据存储细节

<persistence-unit name="ogm-mongodb" transaction-type="JTA">
    <provider>org.hibernate.ogm.jpa.HibernateOgmPersistence</provider>
    <properties>
        <property name="hibernate.ogm.datastore.provider" value="MONGODB" />
        <property name="hibernate.ogm.datastore.database" value="TestDB" />
        <property name="hibernate.ogm.datastore.create_database" value="true" />
    </properties>
</persistence-unit>

Note the definitions we’ve provided here:

请注意我们在这里提供的定义。

  • the value of attribute transaction-type as “JTA” (this implies that we want a JTA entity manager from the EntityManagerFactory)
  • the provider, which is HibernateOgmPersistence for Hibernate OGM
  • a few additional details related to the DB (these typically vary between different data sources)

The configuration assumes MongoDB is running and accessible on defaults. If this is not the case, we can always provide details as necessary. One of our previous articles also covers setting up MongoDB in detail.

该配置假定MongoDB正在运行,并且在默认情况下可以访问。如果情况并非如此,我们可以随时根据需要提供详细信息。我们之前的一篇文章也涵盖了设置MongoDB的细节

4. Entity Definition

4.实体的定义

Now that we’ve gone through the basics, let’s define some entities. If we worked with Hibernate ORM or JPA before, this has nothing more to add. This is the fundamental premise of Hibernate OGM. It promises to let us work with different NoSQL datastores with just the knowledge of JPA.

现在我们已经完成了基础知识的学习,让我们来定义一些实体。如果我们以前使用过Hibernate ORM或JPA,这就没有什么可补充的了。这就是Hibernate OGM的基本前提。它承诺让我们仅凭JPA的知识就能与不同的NoSQL数据集一起工作

For this tutorial, we’ll define a simple object model:

对于本教程,我们将定义一个简单的对象模型。

Domain Model

It defines Article, Author and Editor classes along with their relationships.

它定义了文章作者编辑类,以及它们的关系。

Let’s also define them in Java:

让我们也用Java来定义它们。

@Entity
public class Article {
    @Id
    @GeneratedValue(generator = "uuid")
    @GenericGenerator(name = "uuid", strategy = "uuid2")
    private String articleId;
    
    private String articleTitle;
    
    @ManyToOne
    private Author author;

    // constructors, getters and setters...
}
@Entity
public class Author {
    @Id
    @GeneratedValue(generator = "uuid")
    @GenericGenerator(name = "uuid", strategy = "uuid2")
    private String authorId;
    
    private String authorName;
    
    @ManyToOne
    private Editor editor;
    
    @OneToMany(mappedBy = "author", cascade = CascadeType.PERSIST)
    private Set<Article> authoredArticles = new HashSet<>();

    // constructors, getters and setters...
}
@Entity
public class Editor {
    @Id
    @GeneratedValue(generator = "uuid")
    @GenericGenerator(name = "uuid", strategy = "uuid2")
    private String editorId;
    
    private String editorName;
    @OneToMany(mappedBy = "editor", cascade = CascadeType.PERSIST)
    private Set<Author> assignedAuthors = new HashSet<>();

    // constructors, getters and setters...
}

We’ve now defined entity classes and annotated them with JPA standard annotations:

我们现在已经定义了实体类,并用JPA标准注解对其进行了注解。

  • @Entity to establish them as JPA entities
  • @Id to generate primary keys for the entities with UUIDs
  • @OneToMany and @ManyToOne to establish bidirectional relationships between the entities

5. Operations

5.运营

Now that we’ve created our entities, let’s see if we can perform some operations on them. As a first step, we’ll have to generate some test data. Here, we’ll create an Editor, a few Author, and some Article. We’ll also establish their relationships.

现在我们已经创建了我们的实体,让我们看看我们是否可以对它们进行一些操作。作为第一步,我们必须生成一些测试数据。在这里,我们将创建一个编辑,一些作者,和一些文章。我们还将建立它们的关系。

Thereafter, before we can perform any operation, we’ll need an instance of EntityManagerFactory. We can use this to create EntityManager. Along with this, we need to create TransactionManager to handle transaction boundaries.

此后,在执行任何操作之前,我们需要一个EntityManagerFactory的实例。我们可以用它来创建EntityManager。与此同时,我们需要创建TransactionManager来处理事务边界。

Let’s see how we can use these to persist and retrieve the entities we created earlier:

让我们看看我们如何使用这些来持久化和检索我们先前创建的实体。

private void persistTestData(EntityManagerFactory entityManagerFactory, Editor editor) 
  throws Exception {
    TransactionManager transactionManager = 
      com.arjuna.ats.jta.TransactionManager.transactionManager();
    transactionManager.begin();
    EntityManager entityManager = entityManagerFactory.createEntityManager();
    
    entityManager.persist(editor);
    entityManager.close();
    transactionManager.commit();
}

Here, we are using EntityManager to persist the root entity, which cascades to all its relations. We are also performing this operation within a defined transaction boundary.

在这里,我们使用EntityManager来持久化根实体,并将其级联到所有关系上。我们还在一个定义好的事务边界内执行这个操作。

Now we’re ready to load the entity that we just persisted and verify its contents. We can run a test to verify this:

现在我们准备加载我们刚刚持久化的实体并验证其内容。我们可以运行一个测试来验证这一点。

@Test
public void givenMongoDB_WhenEntitiesCreated_thenCanBeRetrieved() throws Exception {
    EntityManagerFactory entityManagerFactory = 
      Persistence.createEntityManagerFactory("ogm-mongodb");
    Editor editor = generateTestData();
    persistTestData(entityManagerFactory, editor);
    
    TransactionManager transactionManager = 
      com.arjuna.ats.jta.TransactionManager.transactionManager();  
    transactionManager.begin();
    EntityManager entityManager = entityManagerFactory.createEntityManager();
    Editor loadedEditor = entityManager.find(Editor.class, editor.getEditorId());
    
    assertThat(loadedEditor).isNotNull();
    // Other assertions to verify the entities and relations
}

Here, we’re using the EntityManager again to find the data and perform standard assertions on it. When we run this test, it instantiates the datastore, persists the entities, retrieves them back, and verifies.

在这里,我们再次使用EntityManager来查找数据并对其执行标准断言。当我们运行这个测试时,它实例化了数据存储,持久化了实体,检索了实体,并进行了验证。

Again, we’ve just used JPA to persist the entities along with their relationship. Similarly, we use JPA to load the entities back and it all works fine, even when our database choice is MongoDB instead of a traditional relational database.

同样,我们只是使用JPA来持久化实体以及它们的关系。同样地,我们使用JPA来加载实体,这一切都很正常,即使我们的数据库选择的是MongoDB而不是传统的关系型数据库。

6. Switching Backend

6.切换后端

We can also switch our backend. Let’s find out now how difficult it’ll be to do this.

我们也可以切换我们的后端。现在让我们来看看这样做有多难。

We’ll change our backend to Neo4j, which happens to be a popular graph-oriented datastore.

我们将把我们的后端改为Neo4j,它正好是一个流行的面向图的数据存储

Firstly, let’s add the Maven dependency for Neo4j:

首先,让我们添加Neo4j的Maven依赖项

<dependency>
    <groupId>org.hibernate.ogm</groupId>
    <artifactId>hibernate-ogm-neo4j</artifactId>
    <version>5.4.0.Final</version>
</dependency>

Next, we’ll have to add the relevant persistence unit in our persistence.xml:

接下来,我们必须在我们的persistence.xml中添加相关的持久化单元。

<persistence-unit name="ogm-neo4j" transaction-type="JTA">
    <provider>org.hibernate.ogm.jpa.HibernateOgmPersistence</provider>
    <properties>
        <property name="hibernate.ogm.datastore.provider" value="NEO4J_EMBEDDED" />
        <property name="hibernate.ogm.datastore.database" value="TestDB" />
        <property name="hibernate.ogm.neo4j.database_path" value="target/test_data_dir" />
    </properties>
</persistence-unit>

In short, these are the very basic configurations required for Neo4j. This can be detailed further as required.

简而言之,这些是Neo4j所需的非常基本的配置。这可以根据需要进一步详细说明

Well, that’s pretty much what needs to be done. When we run the same test with Neo4j as the backend datastore, it works pretty seamlessly.

嗯,这几乎是需要做的事情。当我们用Neo4j作为后端数据存储运行同样的测试时,它的工作是非常无缝的。

Note that we’ve switched our backend from MongoDB, which happens to be a document-oriented datastore, to Neo4j, which is a graph-oriented datastore. And we did all this with minimal changes and without needing any changes in any of our operations.

请注意,我们已经将我们的后端从MongoDB换成了Neo4j,后者恰好是一个面向文档的数据存储,是一个面向图的数据存储。而且我们在做这一切的时候只做了最小的改动,不需要对我们的任何操作进行任何改动

7. Conclusion

7.结论

In this article, we’ve gone through the basics of Hibernate OGM, including its architecture. Subsequently, we implemented a basic domain model and performed various operations using various DBs.

在这篇文章中,我们已经了解了Hibernate OGM的基础知识,包括其架构。随后,我们实现了一个基本的领域模型,并使用各种数据库进行了各种操作。

As always, the code for the examples is available over on GitHub.

像往常一样,这些例子的代码可以在GitHub上找到over