跳到主要内容

从 SDN+OGM 迁移到 SDN

DeepSeek V3 中英对照 Migrating from SDN+OGM to 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,你无法在不升级整个应用程序的情况下完成这一操作。这是为什么呢?由于你选择将数据库嵌入到应用程序中,你将自己与配置该嵌入式数据库的模块绑定在了一起。要使用另一个嵌入式数据库版本,你必须升级配置它的模块,因为旧版本不支持新的数据库。由于总有一个与 Neo4j-OGM 对应的 Spring Data 版本,你也必须升级它。而 Spring Data 又依赖于 Spring 框架,因此第一点中的论点也同样适用。

不确定要包含哪些构建模块

正确地理解这些术语并不容易。我们在这里这里编写了 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 并配置了一个 URL,例如 [user:password@localhost:7474](http://user:password@localhost:7474)。该依赖需要替换为 org.neo4j:neo4j-ogm-bolt-driver,并且你需要配置一个 Bolt URL,例如 bolt://localhost:7687 或使用新的 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://localhost:7687
spring.data.neo4j.username=neo4j
spring.data.neo4j.password=secret

# New
spring.neo4j.uri=bolt://localhost:7687
spring.neo4j.authentication.username=neo4j
spring.neo4j.authentication.password=secret
properties
注意

这些新属性在未来可能会再次发生变化,当 SDN 和驱动程序最终完全取代旧设置时。

最后,添加新的依赖项,请参阅入门指南了解 Gradle 和 Maven 的操作步骤。

然后你就可以开始替换注释了:

旧版本新版本
org.neo4j.ogm.annotation.NodeEntityorg.springframework.data.neo4j.core.schema.Node
org.neo4j.ogm.annotation.GeneratedValueorg.springframework.data.neo4j.core.schema.GeneratedValue
org.neo4j.ogm.annotation.Idorg.springframework.data.neo4j.core.schema.Id
org.neo4j.ogm.annotation.Propertyorg.springframework.data.neo4j.core.schema.Property
org.neo4j.ogm.annotation.Relationshiporg.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 已被移除且没有替代品。为什么呢?我们认为,创建模式(即使对于无模式数据库)并不属于领域建模的一部分。你可能会说 SDN 模型就是模式,但我们会回答,我们更倾向于命令查询分离,这意味着我们更愿意定义独立的读取和写入模型。这些模型在编写“乏味”的内容和读取图状答案时非常有用。

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

然而,最好的论点是关于生产环境的:虽然所有生成模式的工具在开发过程中确实非常有帮助,尤其是在强制使用严格模式的数据库中,但在生产环境中它们往往并不那么友好:你如何处理同时运行的不同版本的应用程序?版本 A 断言了由较新版本 B 创建的索引?

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

从以前的 Neo4j-OGM 注解迁移会影响到 @Index@CompositeIndex@Required,这里在 使用 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;
}
java

它的注解相当于以下 Cypher 中的模式(截至 Neo4j 4.2):

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);
cypher

使用 @Index 而不带 unique = true 等同于 CREATE INDEX movie_title_index FOR (m:Movie) ON (m.title)。需要注意的是,唯一索引已经隐含了索引的存在。