如需最新的稳定版本,请使用 Spring Data Neo4j 7.4.0spring-doc.cn

开始

我们为 SDN 提供了一个 Spring Boot Starters。 请通过依赖项管理包含入门模块,并配置要使用的 Bolt URL,例如 . Starters假定服务器已禁用身份验证。 由于 SDN Starters依赖于 Java 驱动程序的Starters,因此此处提到的有关配置的所有内容也适用于此处。 有关可用属性的参考,请在命名空间中使用 IDE 自动完成。spring.neo4j.uri=bolt://localhost:7687spring.neo4jspring-doc.cn

SDN 支持spring-doc.cn

这些都包含在同一个二进制文件中。 反应式编程模型在数据库端需要一个 4+ Neo4j 服务器,另一方面需要一个反应式 Spring。spring-doc.cn

准备数据库

在这个例子中,我们停留在电影图中,因为它在每个 Neo4j 实例中都是免费的。spring-doc.cn

如果您没有正在运行的数据库但安装了 Docker,请运行:spring-doc.cn

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

您现在可以访问 http://localhost:7474。 上述命令将服务器的密码设置为 。 请注意提示符 () 中准备运行的命令。 执行它以使用一些测试数据填充您的数据库。secret:play moviesspring-doc.cn

创建新的 Spring Boot 项目

设置 Spring Boot 项目的最简单方法是 start.spring.io(如果您不想使用该网站,它也集成在主要的 IDE 中)。spring-doc.cn

选择 “Spring Web Starter” 以获取创建基于 Spring 的 Web 应用程序所需的所有依赖项。 Spring Initializr 将负责为您创建一个有效的项目结构,并为所选的构建工具准备好所有文件和设置。spring-doc.cn

使用 Maven

你可以向 Spring Initializer 发出 curl 请求,以创建一个基本的 Maven 项目:spring-doc.cn

使用 Spring Initializr 创建一个基本的 Maven 项目
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 -

这将创建一个新文件夹 。 由于此 starter 尚未在初始化器上,因此您必须手动将以下依赖项添加到您的 :Neo4jSpringBootExamplepom.xmlspring-doc.cn

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

如果是现有项目,您还可以手动添加依赖项。spring-doc.cn

使用 Gradle

思路是一样的,只需生成一个 Gradle 项目即可:spring-doc.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.gradlespring-doc.cn

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

如果是现有项目,您还可以手动添加依赖项。spring-doc.cn

配置项目

现在,在您最喜欢的 IDE 中打开这些项目中的任何一个。 查找并配置您的 Neo4j 凭证:application.propertiesspring-doc.cn

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

这是连接到 Neo4j 实例所需的最低要求。spring-doc.cn

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

配置 Neo4j Cypher-DSL

根据您运行应用程序的 Neo4j 版本, 建议配置 Neo4j Cypher-DSL 运行时使用的方言。 使用的默认方言面向 Neo4j 4.4。作为 Neo4j 的 LTS 版本。 这可以通过定义 Cypher-DSL bean 来更改。Configurationspring-doc.cn

让 Cypher-DSL 使用 Neo4j 5 方言
@Bean
Configuration cypherDslConfiguration() {
	return Configuration.newConfig()
                .withDialect(Dialect.NEO4J_5).build();
}
尽管 Spring Data Neo4j 尽最大努力与 Neo4j 5 和默认方言的组合兼容, 始终建议显式定义 dialect。 例如,它将导致更优化的查询,并用于更新的 Neo4j 版本。elementId()

在 module-path 上运行

Spring Data Neo4j 可以在 module 路径上运行。它的自动模块名称是 。 由于当前 Spring Data 构建设置中的限制,它本身不提供模块。 因此,它使用自动但稳定的模块名称。但是,它确实取决于 一个模块化库 (Cypher-DSL)。如果没有 due to 上述限制,我们无法代表您表达对该库的要求。spring.data.neo4jmodule-info.javaspring-doc.cn

因此,在模块路径上运行 Spring Data Neo4j 6.1+ 所需的最低要求 如下所示:module-info.javaspring-doc.cn

A 在应该在模块路径上使用 Spring Data Neo4j 的项目中module-info.java
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.domainspring.beansspring.contextspring.data.commons

创建您的域

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

示例 Node-Entity

SDN 完全支持 Java 和 Kotlin 中的类的不可修改实体。 因此,我们在这里将重点介绍不可变实体,MovieEntity.java显示了这样一个实体。dataspring-doc.cn

SDN 支持 Neo4j Java 驱动程序支持的所有数据类型,请参阅“密码类型系统”一章中的将 Neo4j 类型映射到本地语言类型。 未来版本将支持其他转换器。
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 标签。 如果您只使用 plain ,则标签默认为类的名称。@Node
2 每个实体都必须有一个 id。 此处显示的 movie 类使用该属性作为唯一的业务键。 如果您没有这样的唯一密钥,则可以使用 和 的组合来配置 SDN 以使用 Neo4j 的内部 ID。 我们还为 UUID 提供生成器。title@Id@GeneratedValue
3 这显示为对字段使用与图形属性不同的名称的一种方式。@Property
4 这将定义与 type 和 relationship type 类的关系PersonEntityACTED_IN
5 这是应用程序代码要使用的构造函数。

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

如果您没有找到一个好的业务密钥或不想使用 ID 生成器,以下是使用内部生成的 id 以及常规构造函数和 SDN 使用的所谓 wither-Method 的同一实体:spring-doc.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 这就是所谓的 -attribute 的 wither。 它会创建一个新实体并相应地设置字段,而无需修改原始实体,从而使其不可变。id

当然,您可以将 SDN 与 Kotlin 结合使用,并使用 Kotlin 的数据类对您的域进行建模。如果您想或需要纯粹停留在 Java 中,那么 Lombok 项目是一个替代方案。spring-doc.cn

声明 Spring Data 存储库

您基本上有两个选项: 您可以使用 SDN 以与存储无关的方式工作,并使特定于域的扩展spring-doc.cn

  • org.springframework.data.repository.Repositoryspring-doc.cn

  • org.springframework.data.repository.CrudRepositoryspring-doc.cn

  • org.springframework.data.repository.reactive.ReactiveCrudRepositoryspring-doc.cn

  • org.springframework.data.repository.reactive.ReactiveSortingRepositoryspring-doc.cn

相应地选择 imperative 和 reactive 。spring-doc.cn

虽然从技术上讲并不禁止,但不建议在同一应用程序中混合使用命令式和反应式数据库访问。 我们不会在此类情况下为您提供支持。

另一种选择是确定特定于 store 的实现并获得我们支持的所有开箱即用的方法。 这种方法的优点也是它最大的缺点:一旦推出,所有这些方法都将成为您 API 的一部分。 大多数时候,拿走一些东西比在之后添加东西更难。 此外,使用 store specifics 会将您的 store 泄漏到您的域中。 从性能的角度来看,没有惩罚。spring-doc.cn

适合上述任何 movie 实体的响应式存储库如下所示:spring-doc.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);
}
测试响应式代码是通过 . 请查看 Project Reactor 的相应文档或查看我们的示例代码。reactor.test.StepVerifier