Un guide pour OGM d’Hibernate

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:

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:

image

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.

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.