Статьи

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

Давным-давно на графике далеко-далеко я написал сообщение в блоге, в котором подробно рассказывал, как я использовал Spring Data Neo4j (SDN) для создания инструмента / магазина для исследования видеоигр, используя API-интерфейс GiantBomb.com и мощь Neo4j. с Spring и Spring MVC (прыгайте в мою машину времени и проверьте это здесь ).

(Личное примечание: я все еще чувствую, что мое уважение к сети магазинов программного обеспечения Babbage, фону Нейману, якобы является лучшим именем для магазина программного обеспечения с тех пор, как Babbage был закрыт несколько лет назад.)

В этой серии мы сосредоточимся только на тех аспектах инструмента исследования, которые касаются использования Spring Data Neo4j 4.0, то есть код, который выполняет импорт из API GiantBomb.com, не детализирован, если только вы не хотите этого.

Но почему?

Отличный вопрос!

Короче говоря, хотя SDN 3.x был (и остается) отличным инструментом интеграции, объединяющим мощь Neo4j с выразительностью Spring Data, он не лишен недостатков. Изначально разработанная для использования с Neo4j в «встроенном режиме», команда SDN адаптировала инструмент интеграции для использования с Neo4j в «режиме сервера», когда Neo в конечном итоге представила эту функцию.

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

Хотя производительность постепенно увеличивалась с последующими выпусками, она все еще не соответствовала SDN, работающему против Neo4j во встроенном режиме — что не очень хорошо для тех, кто хочет отделить свой уровень данных от уровня приложений.

Столкнувшись с такими проблемами, команда SDN сделала то, что большинство инженеров любят / предпочитают / молятся делать:

Переписать с нуля!

Команда SDN сделала то, что сделала бы любая хорошая команда инженеров: они взяли на вооружение лучшие возможности «старой» SDN и уроки, извлеченные из разработки и обслуживания SDN, и создали более сильную и быструю реализацию Spring Data Neo4j с акцентом на Neo4j работает в «режиме сервера».

Введите данные Spring Neo4j 4.0!

(* Реплика фанфары и конфетти *)

Теперь команда SDN предоставила в качестве части своей документации руководство по миграции, чтобы упростить переход для тех, кто ранее использовал Spring Data Neo4j 3.x и более ранние версии. Проверьте это здесь .  

Это также является целевой аудиторией для этого поста (какое совпадение!), Поэтому мы рассмотрим некоторые конкретные моменты, с которыми я столкнулся при переносе хранилища Фон Неймана из Spring Data Neo4j 3.x в 4.0.

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

Основы

зависимости

В этом проекте используется Spring 4.2.2, поэтому убедитесь, что у вас самая последняя и самая лучшая версия Spring.

Хотя мне еще предстоит переключиться на Gradle, я слышу хорошие вещи. Тем не менее, магазин Von Neumann’s Store основан на Maven, как и все мои любимые проекты на базе Spring. Итак, что нам нужно в нашем POM, чтобы свернуть Spring Data Neo4j 4.0?

        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-neo4j</artifactId>
            <version>4.0.0.RELEASE</version>
        </dependency>

(Конечно, не стесняйтесь маркировать версию.)

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

конфигурация

В настоящее время одним большим отличием от SDN 4.0 является отсутствие конфигурации на основе XML. Команда SDN планирует исправить эту ситуацию в будущем.

Таким образом, это означает, что на данный момент у нас осталась конфигурация на основе Java. Но, учитывая, что оригинальный фон Неймана был старомодным, была использована конфигурация на основе XML! Рут Рох!

Конечно, это должно быть распространенной моделью миграции. (Да, и не называй меня «Конечно».)

Не бояться! Как известно большинству разработчиков Spring, вы можете смешивать конфигурации на основе XML и Java.

Так как это может выглядеть?

Давайте сначала рассмотрим несколько ключевых строк из начала нашего файла web.xml:

<web-app>
  <!-- web-app attributes and name spaces left out for the sake of brevity -->

  <context-param> 
      <param-name>contextClass</param-name>
      <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>     
  </context-param>

  <context-param> 
      <param-name>contextConfigLocation</param-name> 
      <param-value>com.vonneumanns.config.StoreConfiguration</param-value> 
  </context-param>

  <listener> 
      <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  ...
  </web-app>
  1. Первый раздел содержит некоторую поддержку аннотаций для нашего класса конфигурации, а также поддержку некоторых других функций, необходимых нашему приложению Spring MVC.

  2. Второй раздел сообщает приложению, где найти нашу конфигурацию на основе Java, которая содержит нашу конфигурацию Spring Data Neo4j (мы поговорим об этом подробнее ниже).

  3. Третий раздел — это стандартная загрузка для запуска / завершения корневого WebApplicationContext Spring MVC  .

Посмотрим на часть сервлета нашего файла web.xml:

<servlet>
<servlet-name>vonneumannsweb</servlet-name> 
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param> 
<param-name>contextConfigLocation</param-name> 
<param-value>/WEB-INF/resources/vonneumannsweb-servlet.xml</param-value>
</init-param> 
<load-on-startup>1</load-on-startup>
    ...
</servlet>

Здесь мы просто сообщаем Spring о расположении нашей конфигурации на основе XML, которая в данном случае содержит только ссылку для загрузки любых ресурсов для Spring MVC и ссылку для импорта bean-компонентов из XML-конфигурации старого фон Неймана.

Получить к фактической конфигурации!

Ладно ладно. Блин, дай разработчику перерыв!

Итак, первое, что следует отметить, это то, что все, что было сделано со старой конфигурацией на основе XML, — это удаление всех зависимостей на основе SDN. Фактически, все, что нам осталось, это:

<?xml version="1.0"?>
<beans>
    <!-- once again, attributes and namespace definitions left out for brevity -->

    <context:annotation-config/>

    <context:component-scan base-package="com.vonneumanns.controllers"/>

    <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"/>
    <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/> 

    <bean id="viewResolver"
        class="org.springframework.web.servlet.view.UrlBasedViewResolver">
        <property name="viewClass"
            value="org.springframework.web.servlet.view.JstlView" />
        <property name="prefix" value="/WEB-INF/views/" />
        <property name="suffix" value=".jsp" />
    </bean> 
</beans>

Довольно стандартные вещи.

Теперь давайте посмотрим на конфигурацию на основе Java и части, относящиеся к SDN 4.0:

@Configuration
@EnableNeo4jRepositories(basePackages = "com.vonneumanns.repositories")
@EnableTransactionManagement
@ComponentScan(excludeFilters = @Filter(type=FilterType.ANNOTATION, value={org.springframework.stereotype.Controller.class}),
        basePackages = "com.vonneumanns")
public class StoreConfiguration extends Neo4jConfiguration {
    private final String NEO4J_USERNAME = "neo4j";
    private final String NEO4J_PASSWORD = "madgraph3r"; // the '3' makes it 1337

    @Bean
    public Neo4jServer neo4jServer() {
        return new RemoteServer("http://neo4j-server:7474", this.NEO4J_USERNAME, this.NEO4J_PASSWORD);
    }

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

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

    ...
}

Честно говоря, здесь мало что происходит, и это здорово! Давайте пройдемся по конфигурации, не так ли?

Аннотации

@Configuration
@EnableNeo4jRepositories(basePackages = "com.bhsconsultants.vonneumanns.repositories")
@EnableTransactionManagement
@ComponentScan(excludeFilters = @Filter(type=FilterType.ANNOTATION, value={org.springframework.stereotype.Controller.class}),
        basePackages = "com.bhsconsultants.vonneumanns")
  • @Configuration  — это стандартная аннотация Spring для обозначения класса ожидания.

  • @ EnableNeo4jRepositories сообщает конфигурации, чтобы мы могли использовать SDN-реализацию удобных интерфейсов репозитория Spring Data. Эти репозитории аналогичны предыдущим версиям SDN, и мы обсудим их в следующем посте.

  • @EnableTransactionManagement  имеет решающее значение для включения нашей любимой функции корпоративной базы данных, соответствия ACID. SDN автоматически внедрит свой диспетчер транзакций в контейнер Spring для использования в запросах SDN.

  • @ComponentScan  не является специфичным для SDN, но необходим в этом приложении. Зачем? Поскольку у нас есть классы , аннотированные @Controller, в пакетах, отличных от тех, которые будет использовать SDN, а именно в пакете, который содержит контроллеры Spring MVC.  У вас будут проблемы, если вы попытаетесь использовать @ComponentScan без разбора в таком проекте.   Я нашел трудный путь (с некоторыми менее полезными сообщениями об ошибках).

Определение класса

Groovy! На определение класса:

public class StoreConfiguration extends Neo4jConfiguration {
  ...
}

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

методы

Теперь перейдем к мясу и картошке в комплектации. Давайте рассмотрим каждый метод в классе конфигурации в отдельности.

    @Bean
    public Neo4jServer neo4jServer() {
        return new RemoteServer("http://morpheus:7474", this.NEO4J_USERNAME, this.NEO4J_PASSWORD);
    }

Этот метод сообщает SDN, где расположен сервер Neo4j.  Обратите внимание, что в настоящее время SDN 4.0 поддерживает только Neo4j, работающий в «режиме сервера», т.е. «встроенный режим» не является опцией для использования с SDN 4.0.  Будущие выпуски SDN, вероятно, исправят это.

Мы просто передаем  конструктору RemoteServer URI-адрес сервера и любые учетные данные, необходимые для входа в систему (начиная с Neo4j 2.3, учетные данные для входа требуются по умолчанию; при необходимости их можно отключить в самой конфигурации Neo4j, но я бы не советовал Это).

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

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

Что это? Сессии? Сессионная фабрика? В SDN? Для чего?

Эта концепция «сессии» является новой для Spring Data Neo4j. Мы рассмотрим сеансы в следующем посте, но сейчас (и особенно для веб-приложений) необходимо реализовать этот метод получения фабрики сеансов.

В getSessionFactory () мы передаем  конструктору SessionFactory пакет, содержащий сущности POJO, которые представляют те сущности, которые используются в нашем графе.

В getSession () мы просто возвращаем сеанс по умолчанию из  класса Neo4jConfiguration . Мы также обсудим концепцию охвата этих сессий в следующем посте.

(Если вам интересно, сеансы действительно не нужны — или даже не используются — когда вы разрабатываете приложение, не основанное на веб-технологиях, так что вы можете полностью исключить средство получения сеанса.)

Вывод

И это все по основам! Ну, по крайней мере, насколько зависят и конфигурации.

В следующем посте мы обсудим сессии немного подробнее и посмотрим, что еще нового или отличается (или то же самое!) От предыдущих версий Spring Data Neo4j.

Спасибо за прочтение!