从 SDN+OGM 迁移到 SDN

过去 SDN+OGM 迁移的已知问题

SDN+OGM 多年来一直有着丰富的历史,我们理解迁移大型应用系统既不有趣也无法带来即时利润。我们在从旧版本 Spring Data Neo4j 迁移到新版本时观察到的主要问题大致按以下顺序排列:

跳过多次主要升级

虽然 Neo4j-OGM 可以独立使用,但 Spring Data Neo4j 不行。它在很大程度上依赖于 Spring Data,进而依赖于 Spring Framework 本身,这最终会影响应用程序的很大一部分。根据应用程序的结构方式,也就是说,框架的任何部分渗透到业务代码的程度,您需要调整应用程序的程度就越大。如果您在应用程序中拥有多个 Spring Data 模块,或者在与图数据库相同的服务层访问关系数据库,情况会更糟。更新两个对象映射框架并非易事。

依赖通过 Spring Data 本身配置的嵌入式数据库

SDN+OGM 项目中的嵌入式数据库由 Neo4j-OGM 配置。假设您想从 Neo4j 3.0 升级到 3.5,如果不升级整个应用程序,这是不可能的。为什么会这样?因为您选择将数据库嵌入到您的应用程序中,您就将自己绑定到了配置此嵌入式数据库的模块。要拥有另一个嵌入式数据库版本,您必须升级配置它的模块,因为旧模块不支持新数据库。由于 Spring Data 版本始终与 Neo4j-OGM 相对应,您也必须升级它。然而,Spring Data 依赖于 Spring Framework,然后第一个要点中的论点适用。

不确定要包含哪些构建块

正确理解这些术语并非易事。我们在此处撰写了 SDN+OGM 设置的构建块。可能所有这些都是偶然添加的,您正在处理大量冲突的依赖项。

根据这些观察,我们建议在从 SDN+OGM 切换到 SDN 之前,确保您当前应用程序中仅使用 Bolt 或 HTTP 传输。因此,您的应用程序及其访问层在很大程度上独立于数据库版本。从该状态开始,考虑从 SDN+OGM 迁移到 SDN。

准备从 SDN+OGM Lovelace 或 SDN+OGM Moore 迁移到 SDN

Lovelace 发布列车对应于 SDN 5.1.x 和 OGM 3.1.x,而 Moore 对应于 SDN 5.2.x 和 OGM 3.2.x。

首先,您必须确保您的应用程序通过 Bolt 协议在服务器模式下针对 Neo4j 运行,这意味着在三种情况中的两种情况下需要工作

您正在使用嵌入式数据库

您已将 org.neo4j:neo4j-ogm-embedded-driverorg.neo4j:neo4j 添加到您的项目中,并通过 OGM 工具启动数据库。这不再受支持,您必须设置一个标准的 Neo4j 服务器(支持独立和集群)。

上述依赖项必须删除。

从嵌入式解决方案迁移可能是最艰难的迁移,因为您还需要设置一个服务器。然而,它本身会给您带来很大价值:未来,您将能够升级数据库本身,而无需考虑您的应用程序框架以及数据访问框架。

您正在使用 HTTP 传输

您已添加 org.neo4j:neo4j-ogm-http-driver 并配置了一个类似 user:password@localhost:7474 的 URL。该依赖项必须替换为 org.neo4j:neo4j-ogm-bolt-driver,并且您需要配置一个类似 bolt://:7687 的 Bolt URL,或者使用新的 neo4j:// 方案,该方案也负责路由。

您已经间接使用 Bolt

默认的 SDN+OGM 项目使用 org.neo4j:neo4j-ogm-bolt-driver,因此间接使用了纯 Java 驱动。您可以保留现有的 URL。

迁移

一旦您确保您的 SDN+OGM 应用程序通过 Bolt 正常工作,您就可以开始迁移到 SDN。

  • 删除所有 org.neo4j:neo4j-ogm-* 依赖项

  • 不支持通过 org.neo4j.ogm.config.Configuration bean 配置 SDN,相反,所有驱动程序配置都通过我们新的 Java 驱动程序启动器进行。您尤其需要调整 URL 和身份验证的属性,请参阅 新旧属性对比

您不能通过 XML 配置 SDN。如果您使用 SDN+OGM 应用程序执行此操作,请确保您了解 Spring 应用程序的注解驱动或函数式配置。如今最简单的选择是 Spring Boot。有了我们的启动器,除了连接 URL 和身份验证之外的所有必要配置都已经为您完成。
新旧属性对比
# Old
spring.data.neo4j.embedded.enabled=false # No longer supported
spring.data.neo4j.uri=bolt://:7687
spring.data.neo4j.username=neo4j
spring.data.neo4j.password=secret

# New
spring.neo4j.uri=bolt://:7687
spring.neo4j.authentication.username=neo4j
spring.neo4j.authentication.password=secret
这些新属性将来可能会再次更改,当 SDN 和驱动程序最终完全替换旧设置时。

最后,添加新的依赖项,请参阅 Gradle 和 Maven 的入门

然后您就可以替换注解了

org.neo4j.ogm.annotation.NodeEntity

org.springframework.data.neo4j.core.schema.Node

org.neo4j.ogm.annotation.GeneratedValue

org.springframework.data.neo4j.core.schema.GeneratedValue

org.neo4j.ogm.annotation.Id

org.springframework.data.neo4j.core.schema.Id

org.neo4j.ogm.annotation.Property

org.springframework.data.neo4j.core.schema.Property

org.neo4j.ogm.annotation.Relationship

org.springframework.data.neo4j.core.schema.Relationship

org.springframework.data.neo4j.annotation.EnableBookmarkManagement

无替换,不再需要

org.springframework.data.neo4j.annotation.UseBookmark

无替换,不再需要

org.springframework.data.neo4j.annotation.QueryResult

使用投影;不再支持任意结果映射

一些 Neo4j-OGM 注解在 SDN 中尚未有相应的注解,有些永远不会有。我们将随着我们支持更多功能而添加到上述列表中。

书签管理

@EnableBookmarkManagement@UseBookmark 以及 org.springframework.data.neo4j.bookmark.BookmarkManager 接口及其唯一的实现 org.springframework.data.neo4j.bookmark.CaffeineBookmarkManager 都已移除且不再需要。

SDN 在所有事务中都使用书签,无需配置。您可以删除 CaffeineBookmarkManager 的 bean 声明以及对 com.github.ben-manes.caffeine:caffeine 的依赖。

如果您绝对需要,可以按照这些说明禁用自动书签管理。

自动创建约束和索引

SDN 5.3 及更早版本提供了 Neo4j-OGM 的“自动索引管理器”。

@Index@CompositeIndex@Required 已被移除,没有替代。为什么?我们认为创建 schema(即使对于无 schema 数据库)不属于领域建模的一部分。您可以争辩说 SDN 模型就是 schema,但我们会回答说我们更喜欢命令查询分离,这意味着我们宁愿定义单独的读写模型。这些对于编写“无聊”的东西和读取图形状的答案非常方便。

除此之外,其中一些注解及其值与特定的 Neo4j 版本或版本绑定,这使得它们难以维护。

然而,最好的论点是投入生产:虽然所有生成 schema 的工具在开发过程中确实有帮助,尤其是在强制执行严格 schema 的数据库中,但它们在生产中往往不太好:如何处理同时运行的不同版本的应用程序?版本 A 断言由较新版本 B 创建的索引?

我们认为最好提前控制这一点,并建议使用受控的数据库迁移,基于 LiquigraphNeo4j migrations 等工具。后者已在 JHipster 项目内部与 SDN 一起使用。这两个项目的共同点是它们将 schema 的当前版本存储在数据库中,并确保 schema 在更新之前符合预期。

从以前的 Neo4j-OGM 注解迁移会影响 @Index@CompositeIndex@Required,此处 使用 Neo4j-OGM 自动索引管理器的类中给出了这些示例

使用 Neo4j-OGM 自动索引管理器的类
import org.neo4j.ogm.annotation.CompositeIndex;
import org.neo4j.ogm.annotation.GeneratedValue;
import org.neo4j.ogm.annotation.Id;
import org.neo4j.ogm.annotation.Index;
import org.neo4j.ogm.annotation.Required;

@CompositeIndex(properties = {"tagline", "released"})
public class Movie {

    @Id @GeneratedValue Long id;

    @Index(unique = true)
    private String title;

    private String description;

    private String tagline;

    @Required
    private Integer released;
}

它的注解等同于 Cypher 中的以下模式(截至 Neo4j 4.2)

基于 Cypher 的迁移示例
CREATE CONSTRAINT movies_unique_title ON (m:Movie) ASSERT m.title IS UNIQUE;
CREATE CONSTRAINT movies_released_exists ON (m:Movie) ASSERT EXISTS (m.released);
CREATE INDEX movies_tagline_released_idx FOR (m:Movie) ON (m.tagline, m.released);

使用 @Index 而不带 unique = true 等同于 CREATE INDEX movie_title_index FOR (m:Movie) ON (m.title)。请注意,唯一索引已经暗示了一个索引。

© . This site is unofficial and not affiliated with VMware.