Руководство по Hibernate OGM

Руководство по Hibernate OGM

1. обзор

В этом руководстве мы рассмотрим основыHibernate Object/Grid Mapper (OGM).

Hibernate OGM обеспечивает поддержку Java Persistence API (JPA) для хранилищ данных NoSQL. NoSQL - это общий термин, охватывающий широкий спектр хранилищ данных. Например, это относится к хранилищам данных по ключам, документам, столбцам и графам.

2. Архитектура Hibernate OGM

Hibernate traditionally offers an Object Relational Mapping (ORM) engine для реляционных баз данных. Hibernate OGM engine extends its functionality to support NoSQL datastores. Основным преимуществом его использования является согласованность интерфейса JPA в реляционных хранилищах данных и хранилищах данных NoSQL.

Hibernate OGM может обеспечивать абстракцию для ряда хранилищ данных NoSQL благодаря двум ключевым интерфейсам,DatastoreProvider иGridDialect. Поэтому каждое новое хранилище данных NoSQL, которое оно поддерживает, поставляется с реализацией этих интерфейсов.

На сегодняшний день он поддерживает не все хранилища данных NoSQL, но способен работать со многими из них, такими как Infinispan и Ehcache (ключ-значение), MongoDB и CouchDB (документ) и Neo4j (граф).

It also fully supports transactions and can work with standard JTA providers. Во-первых, это может быть предоставлено через контейнер Java EE без какой-либо явной настройки. Более того, мы можем использовать автономный менеджер транзакций JTA, такой как Narayana, в среде Java SE.

3. Настроить

В этом руководстве мы будем использовать Maven для извлечения необходимых зависимостей для работы с Hibernate OGM. Мы также будем использоватьMongoDB.

Чтобы внести ясность, давайте посмотрим, как настроить их для использования в руководстве.

3.1. Maven Зависимости

Давайте посмотрим на зависимости, необходимые для работы с Hibernate OGM и MongoDB:


    org.hibernate.ogm
    hibernate-ogm-mongodb
    5.4.0.Final


    org.jboss.narayana.jta
    narayana-jta
    5.9.2.Final

Здесь мы извлекаем необходимые зависимости через Maven:

3.2. Персистентность

Нам также потребуетсяdefine datastore details в Hibernatepersistance.xml:


    org.hibernate.ogm.jpa.HibernateOgmPersistence
    
        
        
        
    

Обратите внимание на приведенные здесь определения:

  • значение атрибута тип-транзакции как «JTA» (это означает, что нам нужен менеджер объектов JTA изEntityManagerFactory)

  • поставщик, который являетсяHibernateOgmPersistence для Hibernate OGM

  • несколько дополнительных деталей, связанных с БД (обычно они различаются для разных источников данных)

Конфигурация предполагает, что MongoDB работает и доступен по умолчанию. Если это не так, мы всегда можемprovide details as necessary. Одна из наших предыдущих статей также посвященаsetting up MongoDB in detail.

4. Определение сущности

Теперь, когда мы изучили основы, давайте определим некоторые объекты. If we worked with Hibernate ORM or JPA before, this has nothing more to add. Это фундаментальная предпосылка Hibernate OGM. Этоpromises to let us work with different NoSQL datastores with just the knowledge of JPA.

В этом руководстве мы определим простую объектную модель:

image

Он определяет классы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
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...
}

Теперь мы определили классы сущностей и аннотировали их стандартными аннотациями 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, чтобы найти данные и выполнить для них стандартные утверждения. Когда мы запускаем этот тест, он создает экземпляр хранилища данных, сохраняет сущности, извлекает их обратно и проверяет.

И снова у насjust used JPA to persist the entities along with their relationship. Точно так жеwe use JPA to load the entities back, и все это работает нормально, даже если наша база данных выбрана MongoDB вместо традиционной реляционной базы данных.

6. Переключение Backend

Мы также можем переключить наш бэкэнд. Давайте теперь выясним, насколько сложно это будет сделать.

Мы изменим наш бэкэнд наNeo4j, which happens to be a popular graph-oriented datastore.

Во-первых, добавимMaven dependency for Neo4j:


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

Затем нам нужно добавить соответствующую единицу сохранения состояния в нашpersistence.xml:


    org.hibernate.ogm.jpa.HibernateOgmPersistence
    
        
        
        
    

Короче говоря, это самые основные конфигурации, необходимые для Neo4j. Это может бытьdetailed further as required.

Что ж, это примерно то, что нужно сделать. Когда мы запускаем тот же тест с Neo4j, что и внутреннее хранилище данных, он работает довольно легко.

Обратите внимание, что мы переключили наш бэкэнд с MongoDB, который представляет собой хранилище данных, ориентированное на документы, на Neo4j, хранилище данных с графическим интерфейсом. And we did all this with minimal changes and without needing any changes in any of our operations.

7. Заключение

В этой статье мы рассмотрели основы Hibernate OGM, включая его архитектуру. Впоследствии мы реализовали базовую модель предметной области и выполняли различные операции с использованием различных БД.

Как всегда, доступен код для примеровover on GitHub.