快速开始

我们为 SDN 提供了一个 Spring Boot Starters。请通过您的依赖管理包含该Starters模块,并配置要使用的 Bolt URL,例如 spring.neo4j.uri=bolt://localhost:7687。该Starters假设服务器已禁用身份验证。由于 SDN Starters依赖于 Java 驱动程序的Starters,因此所有关于配置的说明均同样适用于此处。有关可用属性的参考,请在 spring.neo4j 命名空间中使用您 IDE 的自动补全功能。spring-doc.cadn.net.cn

这些都包含在同一个二进制文件中。响应式编程模型要求数据库端使用4+版本的Neo4j服务器,而另一端则需要响应式Spring。spring-doc.cadn.net.cn

准备数据库

对于本示例,我们仍停留在 电影图谱 中,该图谱随每个 Neo4j 实例免费提供。spring-doc.cadn.net.cn

如果您没有运行中的数据库但已安装 Docker,请运行:spring-doc.cadn.net.cn

在 Docker 中启动本地 Neo4j 实例。
docker run --publish=7474:7474 --publish=7687:7687 -e 'NEO4J_AUTH=neo4j/secret' neo4j:5

你现在可以访问 http://localhost:7474
上述命令将服务器的密码设置为 secret
注意提示符中准备运行的命令(:play movies)。
执行该命令,以向你的数据库填充一些测试数据。spring-doc.cadn.net.cn

创建一个新的 Spring Boot 项目

设置 Spring Boot 项目最简单的方法是 start.spring.io(该网站也已集成到主流 IDE 中,如果您不想使用网页版,也可以直接在 IDE 内操作)。spring-doc.cadn.net.cn

选择“Spring Web Starter”以获取创建基于Spring的Web应用程序所需的所有依赖项。Spring Initializr将为您创建有效的项目结构,包含所有文件和设置,适用于所选的构建工具。spring-doc.cadn.net.cn

使用 Maven

您可以向 Spring Initializer 发起一个 curl 请求,以创建一个基础的 Maven 项目:spring-doc.cadn.net.cn

创建一个基本的Maven项目,使用Spring Initializr
curl https://start.spring.io/starter.tgz \
  -d dependencies=webflux,data-neo4j  \
  -d bootVersion=3.2.0 \
  -d baseDir=Neo4jSpringBootExample \
  -d name=Neo4j%20SpringBoot%20Example | tar -xzvf -

这将创建一个新文件夹 Neo4jSpringBootExample
由于此Starters尚未在初始化器中,您必须手动将以下依赖项添加到您的 pom.xml 中:spring-doc.cadn.net.cn

在Maven项目中包含spring-data-neo4j-spring-boot-starter
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-neo4j</artifactId>
</dependency>

您还可以在现有项目中手动添加依赖项。spring-doc.cadn.net.cn

使用 Gradle

思路相同,只需生成一个 Gradle 项目:spring-doc.cadn.net.cn

使用 Spring Initializr 创建一个基本的 Gradle 项目
curl https://start.spring.io/starter.tgz \
  -d dependencies=webflux,data-neo4j \
  -d type=gradle-project \
  -d bootVersion=3.2.0 \
  -d baseDir=Neo4jSpringBootExampleGradle \
  -d name=Neo4j%20SpringBoot%20Example | tar -xzvf -

Gradle 的依赖项看起来如下所示,必须添加到 build.gradle 中:spring-doc.cadn.net.cn

在 Gradle 项目中包含 spring-data-neo4j-spring-boot-starter
dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-data-neo4j'
}

您还可以在现有项目中手动添加依赖项。spring-doc.cadn.net.cn

配置项目

现在在您喜欢的 IDE 中打开其中任何一个项目。
找到 application.properties 并配置您的 Neo4j 凭据:spring-doc.cadn.net.cn

spring.neo4j.uri=bolt://localhost:7687
spring.neo4j.authentication.username=neo4j
spring.neo4j.authentication.password=verysecret

这是连接到 Neo4j 实例所需的最基本内容。spring-doc.cadn.net.cn

当您使用此Starters时,无需添加任何驱动程序的程序化配置。SDN 存储库将由该Starters自动启用。

配置 Neo4j Cypher-DSL

根据您运行应用程序所使用的 Neo4j 版本,建议配置 Neo4j Cypher-DSL 所使用的方言。默认使用的方言是针对 Neo4j 5(Neo4j 的长期支持版本)进行优化的。该方言与 Neo4j 5.23+ 及 Neo4j 2025.x 兼容。您可以通过定义一个 Cypher-DSL Configuration bean 来更改此设置。spring-doc.cadn.net.cn

使 Cypher-DSL 使用 Neo4j 4 版本的语法
@Bean
Configuration cypherDslConfiguration() {
	return Configuration.newConfig()
                .withDialect(Dialect.NEO4J_4).build();
}
虽然 Spring Data Neo4j 尽最大努力以确保与 Neo4j 5 和默认方言的组合兼容,但始终建议显式定义方言。例如,这将有助于生成更优化的查询,并在较新的 Neo4j 版本中利用 elementId()

在模块路径上运行

Spring Data Neo4j 可以在模块路径上运行。其自动模块名称为 spring.data.neo4j
由于当前 Spring Data 构建设置的限制,它本身不提供模块。
因此,它使用一个自动但稳定的模块名称。然而,它确实依赖于一个模块化的库(即 Cypher-DSL)。由于上述限制,我们无法为您表达对该库的依赖要求,故缺少一个 module-info.javaspring-doc.cadn.net.cn

因此,为了在模块路径上运行 Spring Data Neo4j 6.1+,您的项目中所需的最低版本 module-info.java 是以下内容:spring-doc.cadn.net.cn

A module-info.java in a project supposed to use Spring Data Neo4j on the module path
module your.module {

	requires org.neo4j.cypherdsl.core;

	requires spring.data.commons;
	requires spring.data.neo4j;

	opens your.domain to spring.core; (1)

	exports your.domain; (2)
}
1 Spring Data Neo4j 使用 Spring Data Commons 及其反射功能,因此您需要将领域包开放给 spring.core 至少。
2 我们假设此处 your.domain 也包含仓库:这些必须被导出,以便 spring.beansspring.contextspring.data.commons 可以访问。如果您不希望将它们向全世界公开,可以将它们限制为仅限于这些模块使用。

创建您的域名

我们的领域层应完成两件事:spring-doc.cadn.net.cn

示例节点-实体

SDN 完全支持不可变实体,适用于 Java 和 Kotlin 中的 data 类。因此,我们将在此处专注于不可变实体,MovieEntity.java 展示了一个这样的实体。spring-doc.cadn.net.cn

SDN 支持 Neo4j Java 驱动程序支持的所有数据类型,请参阅第“Cypher 类型系统”章节中的 将 Neo4j 类型映射到原生语言类型

spring-doc.cadn.net.cn

未来版本将支持额外的转换器。spring-doc.cadn.net.cn

MovieEntity.java
import java.util.ArrayList;
import java.util.List;

import org.springframework.data.neo4j.core.schema.Id;
import org.springframework.data.neo4j.core.schema.Node;
import org.springframework.data.neo4j.core.schema.Property;
import org.springframework.data.neo4j.core.schema.Relationship;
import org.springframework.data.neo4j.core.schema.Relationship.Direction;

@Node("Movie") (1)
public class MovieEntity {

	@Id (2)
	private final String title;

	@Property("tagline") (3)
	private final String description;

	@Relationship(type = "ACTED_IN", direction = Direction.INCOMING) (4)
	private List<Roles> actorsAndRoles = new ArrayList<>();


	@Relationship(type = "DIRECTED", direction = Direction.INCOMING)
	private List<PersonEntity> directors = new ArrayList<>();

	public MovieEntity(String title, String description) { (5)
		this.title = title;
		this.description = description;
	}

	// Getters omitted for brevity

}
1 @Node 用于将此类标记为受管理的实体。它还用于配置 Neo4j 的标签。如果仅使用普通的 @Node,则标签默认为类名。
2 每个实体都必须有一个 id。

spring-doc.cadn.net.cn

此处所示的 movie 类使用属性 title 作为唯一的业务键。spring-doc.cadn.net.cn

如果没有这样的唯一键,您可以使用 @Id@GeneratedValue 的组合来配置 SDN,使其使用 Neo4j 的内部 ID。spring-doc.cadn.net.cn

我们还提供了 UUID 的生成器。spring-doc.cadn.net.cn

3 这展示了如何使用不同的字段名称而非图属性名称,例如以 @Property 表示。
4 这定义了一个与类型为 PersonEntity 的类之间的关系,以及关系类型 ACTED_IN
5 这是您的应用程序代码应使用的构造函数。

一般而言:使用内部生成ID的不可变实体存在一定的矛盾,因为SDN需要一种方法来设置由数据库生成值的字段。spring-doc.cadn.net.cn

如果您找不到一个好的业务主键,或者不想为ID使用生成器,这里展示了使用内部生成的ID、常规构造函数以及所谓的 wither 方法(SDN 中使用的)的相同实体:spring-doc.cadn.net.cn

MovieEntity.java
import org.springframework.data.neo4j.core.schema.GeneratedValue;
import org.springframework.data.neo4j.core.schema.Id;
import org.springframework.data.neo4j.core.schema.Node;
import org.springframework.data.neo4j.core.schema.Property;

import org.springframework.data.annotation.PersistenceConstructor;

@Node("Movie")
public class MovieEntity {

	@Id @GeneratedValue
	private Long id;

	private final String title;

	@Property("tagline")
	private final String description;

	public MovieEntity(String title, String description) { (1)
		this.id = null;
		this.title = title;
		this.description = description;
	}

	public MovieEntity withId(Long id) { (2)
		if (this.id.equals(id)) {
			return this;
		} else {
			MovieEntity newObject = new MovieEntity(this.title, this.description);
			newObject.id = id;
			return newObject;
		}
	}
}
1 这是您的应用程序代码应使用的构造函数。它将 id 设置为 null,因为包含内部 id 的字段永远不应被操作。
2 这是一个所谓的 wither 方法,用于 id 属性。它会创建一个新的实体,并相应地设置该字段,而不修改原始实体,从而使其不可变。

你可以当然使用 SDN 与 Kotlin,并且用 Kotlin 的数据类来模型你的域。 Project Lombok 是一个替代方案,如果你想或者需要完全在 Java 中。spring-doc.cadn.net.cn

声明Spring数据存储库

您基本上有以下两种选择:您可以使用 SDN 以与商店无关的方式进行操作,并使您的特定域扩展其中之一。spring-doc.cadn.net.cn

选择 imperative 或 reactive。spring-doc.cadn.net.cn

虽然技术上并未禁止,但不推荐在同一应用程序中混合使用 imperative 和 reactive 的数据库访问。 我们不会支持此类场景。

另一种选择是选择一个特定于存储的实现,并开箱即用获得我们支持的所有方法。</p><p>这种方法的优势也是其最大的缺点:一旦发布,这些方法将成为您的API的一部分。</p><p>大多数情况下,很难删除东西,而不是以后添加东西。</p><p>此外,使用特定于存储会将您的存储泄露到域中。</p><p>从性能角度来看,没有任何惩罚。spring-doc.cadn.net.cn

适用于上述任何电影实体的响应式存储库如下所示:spring-doc.cadn.net.cn

MovieRepository.java
import reactor.core.publisher.Mono;

import org.springframework.data.neo4j.repository.ReactiveNeo4jRepository;

public interface MovieRepository extends ReactiveNeo4jRepository<MovieEntity, String> {

	Mono<MovieEntity> findOneByTitle(String title);

}
测试响应式代码是通过reactor.test.StepVerifier完成的。请查看Project Reactor相应的文档,或者参阅我们的示例代码。