Un guide pour OGM d'Hibernate
1. Vue d'ensemble
Dans ce tutoriel, nous allons passer en revue les bases deHibernate Object/Grid Mapper (OGM).
Hibernate OGM fournit un support JPA (Java Persistence API) pour les datastores 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 clé-valeur, document, orientées colonne et graphes.
2. L'architecture d'OGM d'Hibernate
Hibernate traditionally offers an Object Relational Mapping (ORM) engine pour les bases de données relationnelles. Hibernate OGM engine extends its functionality to support NoSQL datastores. 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 etGridDialect. Par conséquent, chaque nouveau magasin de données NoSQL qu'il prend en charge est livré avec 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).
It also fully supports transactions and can work with standard JTA providers. Premièrement, cela peut être fourni via le conteneur Java EE sans aucune configuration explicite. De plus, nous pouvons utiliser un gestionnaire de transactions JTA autonome tel que Narayana dans l'environnement Java SE.
3. Installer
Pour ce didacticiel, nous utiliserons Maven pour extraire les dépendances requises pour travailler avec Hibernate OGM. Nous utiliserons égalementMongoDB.
Pour clarifier, voyons comment les configurer pour le didacticiel.
3.1. Dépendances 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:
-
Narayana Transaction Manager (fournisseur réel du JTA)
3.2. Unité de persistance
Nous devrons égalementdefine datastore details dans lespersistance.xml Hibernate:
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 parmi lesEntityManagerFactory)
-
le fournisseur, qui estHibernateOgmPersistence pour 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 est accessible par défaut. Si ce n'est pas le cas, on peut toujoursprovide details as necessary. Un de nos articles précédents couvre également lessetting up MongoDB in detail.
4. Définition d'entité
Maintenant que nous avons passé en revue les principes de base, définissons certaines entités. If we worked with Hibernate ORM or JPA before, this has nothing more to add. C'est la prémisse fondamentale d'HGernate OGM. Ilpromises to let us work with different NoSQL datastores with just the knowledge of JPA.
Pour ce didacticiel, nous allons définir un modèle objet simple:
Il définit les classesArticle,Author etEditor 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 comme 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. Les opérations
Maintenant que nous avons créé nos entités, voyons si nous pouvons effectuer certaines opérations sur elles. Dans un premier temps, nous devrons générer des données de test. Ici, nous allons créer unEditor, quelquesAuthor et desArticle. Nous établirons également leurs relations.
Par la suite, avant de pouvoir effectuer une opération, nous aurons besoin d'une instance deEntityManagerFactory.. Nous pouvons l'utiliser pour créerEntityManager. Parallèlement à cela, nous devons créer desTransactionManager pour gérer les limites des transactions.
Voyons comment nous pouvons les utiliser pour conserver et récupérer les entités que nous avons créées précédemment:
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();
}
Ici, nous utilisonsEntityManager pour conserver l'entité racine, qui tombe en cascade dans toutes ses relations. Nous effectuons également cette opération dans une limite de transaction définie.
Nous sommes maintenant prêts à charger l'entité que nous venons de conserver et à vérifier son contenu. Nous pouvons effectuer un test pour vérifier ceci:
@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
}
Ici, nous utilisons à nouveau lesEntityManager pour trouver les données et y effectuer des assertions standard. Lorsque nous exécutons ce test, il instancie le magasin de données, conserve les entités, les récupère et vérifie.
Encore une fois, nous avonsjust used JPA to persist the entities along with their relationship. De même,we use JPA to load the entities back et tout fonctionne correctement, même lorsque notre choix de base de données est MongoDB au lieu d'une base de données relationnelle traditionnelle.
6. Basculement du backend
Nous pouvons également basculer notre backend. Voyons maintenant à quel point il sera difficile de le faire.
Nous allons changer notre backend enNeo4j, which happens to be a popular graph-oriented datastore.
Tout d'abord, ajoutons lesMaven dependency for Neo4j:
org.hibernate.ogm
hibernate-ogm-neo4j
5.4.0.Final
Ensuite, nous devrons ajouter l'unité de persistance appropriée dans nospersistence.xml:
org.hibernate.ogm.jpa.HibernateOgmPersistence
En bref, ce sont les configurations très basiques requises pour Neo4j. Cela peut êtredetailed 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 en tant que magasin de données principal, cela fonctionne de manière parfaitement transparente.
Notez que nous avons changé notre backend de MongoDB, qui se trouve être une banque de données orientée document, vers Neo4j, qui est une banque de données orientée graph. And we did all this with minimal changes and without needing any changes in any of our operations.
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 disponibleover on GitHub.