Статьи

Улучшение ситуации: миграция данных Spring Neo4j 3.x на 4.0 — сессии и репозитории

Когда мы в последний раз покидали нашу суперсерию, мы представили Spring Data Neo4j (SDN) 4.0, включая некоторые основные сведения, необходимые для миграции и настройки проекта SDN 4.0. В типичном стиле Mad Grapher (т. Е. Мой стиль, каким бы типичным или стильным он ни был, а может и не быть), мы идем через эту миграцию путем замены моего любимого компьютерного магазина, фон Неймана (вы можете проверить мой оригинальный пост из эоны назад здесь ).

В этой статье мы собираемся представить концепцию, новую для Spring Data Neo4j: Sessions.

Нет, не тот тип!

Несмотря на то, что я настоятельно рекомендую покопаться в документации SDN, касающейся сессий, мы собираемся сделать все довольно просто для целей этой статьи.

Введение в сессию

(Или, как я ловлю себя на том, что иногда я называю это «сэш». Мне действительно нужно больше выходить.)

В основе SDN 4.0 лежит реализация модели объектного графа (OGM) Neo4j. Этот OGM сильно зависит от этих «сессий». Фактически, все реализации репозитория SDN и даже сам  класс Neo4jTemplate управляются сессиями.

Для понимания сеанса важно понимать его жизненный цикл. Сеанс отслеживает любые изменения, сделанные как в узлах, так и в отношениях, что делает сохранение обратно в граф особенно эффективным, поскольку сохраняются только те сущности, которые изменились! Это потрясающая новость, особенно если вам приходится работать с большими графиками.

И, чтобы подсластить сделку, сеанс никогда не вернет кэшированные объекты; другими словами, при загрузке сеанс всегда будет попадать в базу данных — устаревшие данные не проблема!

Давайте быстро вернемся к конфигурации на основе Java для сессий, а также к фабрике сессий, которая используется для создания сессий:

    @Bean
    public SessionFactory getSessionFactory() {        
        return new SessionFactory("com.bhsconsultants.vonneumanns.entities");
    }

    @Bean
    @Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
    public Session getSession() throws Exception {
        return super.getSession();
    }

Ничего сверхсложного здесь нет, но давайте подробнее рассмотрим жизненный цикл сеанса, а также фабрики сеансов, которая также может иметь область действия.

Жизненный цикл сессии

Разработчик может настроить жизненный цикл сеанса: можно предположить, что сеанс с более длинной областью действия потребует дополнительных затрат памяти, но приведет к более эффективному выполнению запросов с учетом локального кэша сущностей. Однако, если эти объекты не будут периодически перезагружаться, можно пропустить изменения, сделанные другими пользователями, и в конечном итоге работать с устаревшими объектами.

Если кто-то решит использовать сеансы с более короткой областью действия, накладные расходы памяти практически исключаются, хотя запросы могут быть не такими эффективными, как в противном случае. Это особенно верно для операций сохранения, так как сеанс может не знать об объектах, которые были первоначально загружены, и поэтому обновит все объекты.

Итак, есть компромиссы.

Рекомендуется настроить область сеанса так, чтобы она соответствовала тому, что можно считать «единицей работы» в вашем приложении. 

Из руководства SDN 4.0 :

«Что это означает, зависит от сценария использования, но в типичном веб-приложении Spring мы рекомендуем использовать сеанс в области запросов или в рамках сеансов HTTP. В любом случае, если вы убедитесь, что загружаете свежие данные в начале каждого единица работы, то целостность данных не должна быть проблемой «.

Не следует упускать из виду фабрику сессий. Фабрика сеанса устанавливает любые метаданные отображения графов объектов. Хотя рекомендуется оставить область действия фабрики сеансов такой же, как в приложении, область действия можно установить более узкой, если это необходимо, хотя выгоды от этого, вероятно, будут незначительными.

Итак, что я могу сделать с сеансом?

Поскольку сессия  управляет Neo4jTemplate , и вы, несомненно, знакомы с Neo4jTemplate  прошлого, вы можете себе представить, что сессия — это то, что обеспечивает большинство взаимодействий с самим графом.

Тем не менее, между старым и новым  классами Neo4jTemplate есть существенные различия .

В предыдущих версиях SDN  класс Neo4jTemplate позволял нам напрямую взаимодействовать с узлами и отношениями графа, позволяя создавать отношения, находить конкретные узлы по некоторому индексу и т. Д.

Эти удобства были убраны, применяя более кайферно-ориентированный подход; то есть операции, которые мы обычно выполняем с узлами и отношениями, теперь в основном осуществляются посредством работы с нашими объектами POJO и их сохранения, или с помощью запросов Cypher, отправляемых через  класс Neo4jTemplate . (Тем не менее, вы все равно можете загрузить несколько узлов на основе свойств / типов объектов.)

Давайте посмотрим на быстрый пример.

В моем оригинальном магазине фон Неймана у нас был следующий метод:

public Purchase makePurchase(Neo4jOperations template, Stock item, int quantity)
{
  return template.createRelationshipBetween(this, item, Purchase.class, "PURCHASED", false);
}

Так как createRelationshipBetween (…)  был удален, тот же метод теперь реализован так:

public Purchase makePurchase(Neo4jOperations template, Stock item, int quantity)
{
  final Purchase purchase = new Purchase();
  purchase.setCustomer(this);
  purchase.setItem(item);

  template.save(purchase);

  return purchase;
}

Единственная реальная разница в том, что нам нужно работать с POJO напрямую, а затем вызывать метод save (…) шаблона,  чтобы создать связь.

Не так уж плохо для перемен.

Мы расскажем о работе с PONO / объектами SDN в следующем посте. (Эй, мы должны сохранить некоторые  забавные вещи на потом!)

Ознакомьтесь с документацией для  класса Neo4jTemplate здесь .

Репо (ситории) Человек

Да ладно, вы полностью ожидали этого.

(Предоставлено rogerebert.com)

Поскольку мы обсуждаем сессии и работаем с графиком, мы могли бы также обсудить реализацию SDN интерфейсов репозитория Spring Data Commons.

В предыдущих версиях Spring Data Neo4j мы много полагались на  GraphRepository <T> и RelationshipOperationsRepository <T>  при создании наших собственных репозиториев. Большие изменения были внесены в отношении репозиториев, и вы обнаружите, что единственный репозиторий, который вы будете использовать, — это обновленный  интерфейс GraphRepository с тем же именем. Другие интерфейсы, которые вы могли использовать, были удалены и / или добавлены в этот единственный интерфейс.

Также стоит отметить, что GraphRepository  больше не объединяет IndexRepository и TraversalRepository, так  как оба этих интерфейса больше не поддерживаются.  

Мы рассмотрим поддержку SDN для индексации и обходов в следующем посте.

Новый GraphRepository по-  прежнему поддерживает все операции CRUD, которые вы знаете и любите, а также те же определения методов поиска и методов запросов, которые вы знаете и любите.

Давайте кратко рассмотрим одно из хранилищ Фон Неймана, хорошо?

public interface GameRepository extends GraphRepository<Game> {
Game findByGameId(String id);

@Query("MATCH (g1:Game {gameId: {0} }), (g2:Game {gameId: {1} }), p = shortestPath( (g1)-[*]-(g2) ) RETURN p")
Iterable<Map<String, Object> > getPath(String game1Id, String game2Id);
}

  • При вызове findByGameId найдутся все узлы типа / метки «Game» со свойством «gameId», равным переданной строке «id». Производные методы поиска FTW!

  • getPath  выполнит указанный Cypher-запрос, предоставив необходимые параметры в токенизированных местах. Если вы помните, одной из самых больших проблем, с которыми я столкнулся в предыдущей версии Магазина фон Неймана, была невозможность обхода путей, содержащих произвольные типы узлов и отношений. Хотя это не было решено (и, вероятно, не будет, учитывая статическую природу Java — мы всегда можем использовать отражение или какую-либо другую проверку!), Возможность отобразить обратно в Iterable,  содержащий Map из <String, Object > Пары приближают нас только к тому,

Насколько это круто? («Знаю ли я, что означает« риторический »?!»)

Вывод

В этом посте мы познакомились с парадигмой сессий SDN 4, а также с тем, как она используется и что она означает для разработчиков.  

Кроме того, мы также рассмотрели, как мы можем выполнить некоторые базовые взаимодействия с графом через Neo4jTemplate  и репозитории SDN. Обе эти концепции значительно упрощают работу с графом, упрощая предыдущие методы Spring Data Neo4j.

Я настоятельно рекомендую просматривать обновленные определения интерфейса / класса для SDN 4 всякий раз, когда требуются дополнительные разъяснения.

Вот и все для этого поста! Как всегда, если у вас есть какие-либо вопросы / комментарии / проблемы — или даже если у меня что-то не так — оставляйте комментарии ниже, и я сделаю все возможное, чтобы ответить на них.

В следующий раз мы перейдем к теме, которую вы все, несомненно, ждали: SDN POJO и сущности! Ура!

Увидимся в следующем посте, ребята!