1. 概要

このチュートリアルでは、 Hibernate Object / Grid Mapper(OGM)の基本について説明します。

Hibernate OGMは、NoSQLデータストアのJava Persistence API(JPA)サポートを提供します。 NoSQLは、さまざまなデータストレージを網羅する総称です。 たとえば、これには、キー値、ドキュメント、列指向、およびグラフ指向のデータストアが含まれます。

2. HibernateOGMのアーキテクチャ

Hibernateは従来、リレーショナルデータベース用のオブジェクトリレーショナルマッピング(ORM)エンジンを提供しています。 Hibernate OGMエンジンは、その機能を拡張してNoSQLデータストアをサポートします。これを使用する主な利点は、リレーショナルデータストアとNoSQLデータストア間でのJPAインターフェースの一貫性です。

Hibernate OGMは、DatastoreProviderGridDialectの2つの主要なインターフェースにより、多数のNoSQLデータストアを抽象化できます。 したがって、サポートする新しいNoSQLデータストアにはそれぞれ、これらのインターフェイスの実装が付属しています。

現在、すべてのNoSQLデータストアをサポートしているわけではありませんが、InfinispanとEhcache(キー値)、MongoDBとCouchDB(ドキュメント)、Neo4j(グラフ)などの多くのデータストアと連携できます。

トランザクションも完全にサポートし、標準のJTAプロバイダーと連携できます。まず、これは、明示的な構成なしでJakartaEEコンテナーを介して提供できます。 さらに、JavaSE環境でNarayanaのようなスタンドアロンのJTAトランザクションマネージャーを使用できます。

3. 設定

このチュートリアルでは、Mavenを使用して、HibernateOGMで動作するために必要な依存関係をプルします。 MongoDBも使用します。

明確にするために、チュートリアル用にそれらを設定する方法を見てみましょう。

3.1. Mavenの依存関係

HibernateOGMと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>

ここでは、Mavenを介して必要な依存関係を取得しています。

3.2. 永続性ユニット

また、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>

ここで提供した定義に注意してください。

  • 「JTA」としての属性transaction-typeの値(これは、 EntityManagerFactoryからのJTAエンティティマネージャーが必要であることを意味します)
  • HibernateOGMのHibernateOgmPersistenceであるプロバイダー
  • DBに関連するいくつかの追加の詳細(これらは通常、異なるデータソース間で異なります)

構成では、MongoDBが実行されており、デフォルトでアクセス可能であると想定しています。 そうでない場合は、いつでも必要に応じて詳細を提供できます。 以前の記事の1つでは、MongoDBのセットアップの詳細についても説明しています。

4. エンティティ定義

基本を終えたので、いくつかのエンティティを定義しましょう。 以前にHibernateORMまたはJPAを使用していた場合、これ以上追加することはありません。 これがHibernateOGMの基本的な前提です。 は、JPAの知識だけでさまざまなNoSQLデータストアを操作できるようにすることを約束します。

このチュートリアルでは、単純なオブジェクトモデルを定義します。

Article Author Editorクラスとそれらの関係を定義します。

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...
}

これで、エンティティクラスが定義され、JPA標準のアノテーションが付けられました。

  • @Entity は、それらをJPAエンティティとして確立します
  • @Id は、UUIDを持つエンティティの主キーを生成します
  • @OneToManyおよび@ManyToOneは、エンティティ間の双方向の関係を確立します

5. オペレーション

エンティティを作成したので、それらに対していくつかの操作を実行できるかどうかを見てみましょう。 最初のステップとして、いくつかのテストデータを生成する必要があります。 ここでは、 Editor 、いくつかの Author 、およびいくつかのArticleを作成します。それらの関係も確立します。

その後、操作を実行する前に、EntityManagerFactoryのインスタンスが必要になります。これを使用してEntityManagerを作成できます。 これに加えて、トランザクション境界を処理するためにTransactionManagerを作成する必要があります。

これらを使用して、以前に作成したエンティティを永続化および取得する方法を見てみましょう。

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();
}

ここでは、 EntityManager を使用して、すべての関係にカスケードされるルートエンティティを永続化します。 また、定義されたトランザクション境界内でこの操作を実行しています。

これで、永続化したエンティティをロードして、その内容を確認する準備が整いました。 これを確認するためにテストを実行できます。

@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
}

ここでは、 EntityManager を再度使用してデータを検索し、標準のアサーションを実行しています。 このテストを実行すると、データストアがインスタンス化され、エンティティが永続化され、エンティティが取得されて検証されます。

繰り返しになりますが、 JPAを使用して、エンティティとその関係を永続化しました。 同様に、 JPAを使用してエンティティをロードバックし、データベースの選択が従来のリレーショナルデータベースではなくMongoDBである場合でも、すべて正常に機能します。

6. バックエンドの切り替え

バックエンドを切り替えることもできます。 これを行うのがどれほど難しいかを見てみましょう。

バックエンドをNeo4jに変更します。これは、人気のあるグラフ指向のデータストアです。

まず、Neo4jMaven依存関係を追加しましょう。

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

次に、関連する永続性ユニットを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>

要するに、これらはNeo4jに必要な非常に基本的な構成です。 これは、必要に応じてさらに詳しく説明できます

まあ、それはほとんどやらなければならないことです。 Neo4jでバックエンドデータストアと同じテストを実行すると、非常にシームレスに機能します。

バックエンドを、たまたまドキュメント指向のデータストアであるMongoDBから、グラフ指向のデータストアであるNeo4jに切り替えたことに注意してください。 そして、最小限の変更で、操作の変更を必要とせずに、これらすべてを実行しました

7. 結論

この記事では、アーキテクチャを含むHibernateOGMの基本について説明しました。 その後、基本的なドメインモデルを実装し、さまざまなDBを使用してさまざまな操作を実行しました。

いつものように、例のコードはGitHubから入手できます。