从 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,如果不升级整个应用程序,就不能。 为什么? 当您选择将数据库嵌入到应用程序中时,您将自己与配置此嵌入式数据库的模块捆绑在一起。 要拥有另一个嵌入式数据库版本,您必须升级配置它的模块,因为旧的模块不支持新数据库。 由于始终有一个对应于 Neo4j-OGM 的 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 上运行,这意味着在以下三种情况下的两种情况下都可以工作:
您正在使用 Embedded
您已将 和 添加到您的项目中,并通过 OGM 工具启动数据库。
这不再受支持,您必须设置标准 Neo4j 服务器(支持独立服务器和集群服务器)。org.neo4j:neo4j-ogm-embedded-driver
org.neo4j:neo4j
必须删除上述依赖项。
从嵌入式解决方案迁移可能是最困难的迁移,因为您还需要设置服务器。 然而,它本身就给你带来了很多价值: 将来,您将能够升级数据库本身,而无需考虑您的应用程序框架和数据访问框架。
您使用的是 HTTP 传输
您已添加并配置了类似 .
依赖项必须替换为,并且您需要配置一个 Bolt url ,例如或使用新方案,它也负责路由。org.neo4j:neo4j-ogm-http-driver
user:password@localhost:7474
org.neo4j:neo4j-ogm-bolt-driver
bolt://localhost:7687
neo4j://
迁移
确保 SDN+OGM 应用程序按预期在 Bolt 上运行后,您就可以开始迁移到 SDN。
-
删除所有依赖项
org.neo4j:neo4j-ogm-*
-
不支持通过 bean 配置 SDN,而是驱动程序的所有配置都通过我们的新 Java 驱动程序Starters进行。 您尤其必须调整 url 和 authentication 的属性,请参阅新旧属性比较
org.neo4j.ogm.config.Configuration
您无法通过 XML 配置 SDN。 如果您对 SDN+OGM 应用程序进行了此操作,请确保您了解 Spring 应用程序的注释驱动或功能配置。 如今,最简单的选择是 Spring Boot。 有了我们的Starters,除了连接 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 入门。
然后,您就可以替换注释了:
老 | 新增功能 |
---|---|
|
|
|
|
|
|
|
|
|
|
|
无需更换,无需 |
|
无需更换,无需 |
|
使用投影;不再支持任意结果映射 |
一些 Neo4j-OGM 注解在 SDN 中还没有对应的注解,有些则永远不会有。 由于我们支持其他功能,因此我们将添加到上面的列表中。 |
书签管理
和 以及接口及其唯一的实现都已消失,不再需要。@EnableBookmarkManagement
@UseBookmark
org.springframework.data.neo4j.bookmark.BookmarkManager
org.springframework.data.neo4j.bookmark.CaffeineBookmarkManager
SDN 对所有事务使用书签,无需配置。
您可以删除 的 bean 声明以及 的依赖项。CaffeineBookmarkManager
com.github.ben-manes.caffeine:caffeine
如果绝对必须,您可以按照这些说明禁用自动书签管理。
自动创建约束和索引
SDN 5.3 及之前的版本提供了 Neo4j-OGM 的 “Automatic index manager”。
@Index
,并且已被删除且未进行替换。
为什么?
我们认为创建 schema - 即使是对于无 schema 的数据库 - 也不是域建模的一部分。
您可能会争辩说 SDN 模型就是架构,但比起我们的回答,我们甚至更喜欢 Command-query 分离,
这意味着我们宁愿定义单独的 read 和 write 模型。
这些对于编写 “无聊” 的东西和阅读图形形状的答案非常方便。@CompositeIndex
@Required
除此之外,其中一些注释的值分别与特定的 Neo4j 版本或版本相关联,这使得它们 难以维护。
然而,最好的论点是进入生产环境:虽然所有生成 schema 的工具在开发过程中确实很有帮助,但对于执行严格方案的数据库更是如此, 它们在生产中往往不是那么好:您如何处理同时运行的不同版本的应用程序? 版本 A 断言由较新版本 B 创建的索引?
我们认为最好提前对此进行控制,并建议使用基于 Liquigraph 或 Neo4j 迁移等工具的受控数据库迁移。 后者已在JHipster项目中与SDN一起使用。 这两个项目的共同点是,它们将 schema 的当前版本存储在数据库中,并确保 schema 在更新之前符合预期。
从以前的 Neo4j-OGM 注释迁移会影响 ,并且在使用 Neo4j-OGM 自动索引管理器的 A 类中给出了一个例子:@Index
@CompositeIndex
@Required
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);
使用 without 等同于 .
请注意,唯一索引已经意味着索引。@Index
unique = true
CREATE INDEX movie_title_index FOR (m:Movie) ON (m.title)