Un guide pour Hibernate OGM

1. Vue d'ensemble

Dans ce tutoriel, nous allons passer en revue les bases de Hibernate Object / Grid Mapper (OGM).

Hibernate OGM fournit la prise en charge de l'API Java Persistence (JPA) pour les banques de données NoSQL. NoSQL est un terme générique couvrant une grande variété de stockage de données. Par exemple, cela inclut les banques de données à valeur-clé, document, orientées colonnes et orientées graphique.

2. L'architecture d'Hibernate OGM

Hibernate propose traditionnellement un moteur ORM (Object Relational Mapping) pour les bases de données relationnelles. Le moteur Hibernate OGM étend ses fonctionnalités pour prendre en charge les banques de données NoSQL. Le principal avantage de son utilisation est la cohérence de l'interface JPA entre les banques de données relationnelles et NoSQL.

Hibernate OGM est capable de fournir une abstraction sur un certain nombre de banques de données NoSQL grâce à deux interfaces clés, DatastoreProvider et GridDialect . Par conséquent, chaque nouvelle banque de données NoSQL prise en charge est accompagnée d'une implémentation de ces interfaces.

À ce jour, il ne prend pas en charge toutes les banques de données NoSQL, mais il est capable de fonctionner avec beaucoup d'entre eux comme Infinispan et Ehcache (valeur-clé), MongoDB et CouchDB (document) et Neo4j (graphique).

Il prend également pleinement en charge les transactions et peut fonctionner avec des fournisseurs JTA standard. Tout d'abord, cela peut être fourni via le conteneur Jakarta EE sans aucune configuration explicite. De plus, nous pouvons utiliser un gestionnaire de transactions JTA autonome comme Narayana dans l'environnement Java SE.

3. Configuration

Pour ce didacticiel, nous utiliserons Maven pour extraire les dépendances requises pour fonctionner avec Hibernate OGM. Nous utiliserons également MongoDB.

Pour clarifier, voyons comment les configurer pour le tutoriel.

3.1. Dépendances de Maven

Voyons les dépendances nécessaires pour travailler avec Hibernate OGM et MongoDB:

 org.hibernate.ogm hibernate-ogm-mongodb 5.4.0.Final   org.jboss.narayana.jta narayana-jta 5.9.2.Final 

Ici, nous extrayons les dépendances requises via Maven:

  • Dialecte Hibernate OGM pour MongoDB
  • Narayana Transaction Manager (fournisseur actuel du JTA)

3.2. Unité de persistance

Nous devrons également définir les détails du magasin de données dans le fichier Hibernate persistance.xml :

 org.hibernate.ogm.jpa.HibernateOgmPersistence      

Notez les définitions que nous avons fournies ici:

  • la valeur de l'attribut transaction-type comme «JTA» (cela implique que nous voulons un gestionnaire d' entités JTA de EntityManagerFactory)
  • le fournisseur, qui est HibernateOgmPersistence for Hibernate OGM
  • quelques détails supplémentaires liés à la base de données (ceux-ci varient généralement entre différentes sources de données)

La configuration suppose que MongoDB est en cours d'exécution et accessible par défaut. Si ce n'est pas le cas, nous pouvons toujours fournir des détails si nécessaire. Un de nos articles précédents couvre également la configuration détaillée de MongoDB.

4. Définition de l'entité

Maintenant que nous avons passé en revue les bases, définissons certaines entités. Si nous avons déjà travaillé avec Hibernate ORM ou JPA, cela n'a plus rien à ajouter . C'est la prémisse fondamentale d'Hibernate OGM. Il promet de nous permettre de travailler avec différents datastores NoSQL avec juste la connaissance de JPA .

Pour ce tutoriel, nous allons définir un modèle objet simple:

Il définit les classes Article , Auteur et Editeur ainsi que leurs relations.

Définissons-les également en 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 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 assignedAuthors = new HashSet(); // constructors, getters and setters... }

Nous avons maintenant défini les classes d'entités et les avons annotées avec des annotations standard JPA:

  • @Entity pour les établir en tant qu'entités JPA
  • @Id pour générer des clés primaires pour les entités avec des UUID
  • @OneToMany et @ManyToOne pour établir des relations bidirectionnelles entre les entités

5. Opérations

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.

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.

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.

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.

6. Switching Backend

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.

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

 org.hibernate.ogm hibernate-ogm-neo4j 5.4.0.Final 

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

 org.hibernate.ogm.jpa.HibernateOgmPersistence      

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

Eh bien, c'est à peu près ce qu'il faut faire. Lorsque nous exécutons le même test avec Neo4j que le magasin de données backend, cela fonctionne de manière assez transparente.

Notez que nous avons changé notre backend de MongoDB, qui se trouve être une banque de données orientée document, à Neo4j, qui est une banque de données orientée graph. Et nous avons fait tout cela avec des changements minimes et sans avoir besoin de changements dans aucune de nos opérations .

7. Conclusion

Dans cet article, nous avons passé en revue les bases d'Hibernate OGM, y compris son architecture. Par la suite, nous avons implémenté un modèle de domaine de base et effectué diverses opérations à l'aide de différentes bases de données.

Comme toujours, le code des exemples est disponible à l'adresse over sur GitHub.