跳到主要内容
版本:8.1.1

从 SDN+OGM 迁移到 SDN

Doubao 中英对照 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 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-driver 和 org.neo4j:neo4j,并通过 OGM 设施启动数据库。这种方式已不再受支持,您必须搭建一个标准的 Neo4j 服务器(独立模式和集群模式均受支持)。

必须移除上述依赖。

从内嵌方案迁移可能是最艰难的迁移,因为您还需要搭建服务器。但它本身也最有价值:今后您将能够独立升级数据库本身,而无需考虑应用框架和数据访问框架。

您使用的是 HTTP 传输协议​

您添加了 org.neo4j:neo4j-ogm-http-driver,并配置了类似 [user:password@localhost:7474](http://user:password@localhost:7474) 的 URL。该依赖必须替换为 org.neo4j:neo4j-ogm-bolt-driver,并且您需要配置类似 bolt://localhost: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://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
注意

当 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 创建的索引?

我们认为更好的做法是提前掌控这一点,并建议使用受控的数据库迁移,基于 Liquigraph 或 Neo4j 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;
}

它的注解等价于以下 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);

使用不带 unique = true 的 @Index 等价于 CREATE INDEX movie_title_index FOR (m:Movie) ON (m.title)。请注意,唯一索引本身已经隐含了普通索引。