原题目:Spring认证中国教育管理中心-理解如何在 Neo4j 的 NoSQL 数据存储中长久化对象和关系。(Spring中国教育管理中心)
Spring认证指南:如何在 Neo4j 的 NoSQL 数据存储中长久化对象和关系
本指南将疏导您实现应用Spring Data Neo4j构建应用程序的过程,该应用程序在 Neo4j 中存储数据并从中检索数据,Neo4j是一个基于图形的数据库。
你将建造什么
您将应用 Neo4j 的NoSQL基于图形的数据存储来构建嵌入式 Neo4j 服务器、存储实体和关系以及开发查问。
你须要什么
约15分钟
最喜爱的文本编辑器或 IDE
JDK 1.8或更高版本
Gradle 4+或Maven 3.2+
您还能够将代码间接导入 IDE:弹簧工具套件 (STS)IntelliJ IDEA
如何实现本指南
像大多数 Spring入门指南一样,您能够从头开始并实现每个步骤,也能够绕过您曾经相熟的根本设置步骤。无论哪种形式,您最终都会失去工作代码。
要从头开始,请持续从 Spring Initializr 开始。
要跳过基础知识,请执行以下操作:
下载并解压本指南的源代码库,或应用Git克隆它:git clone https://github.com/spring-gui...
光盘进入gs-accessing-data-neo4j/initial
跳转到定义一个简略实体。
实现后,您能够对照中的代码查看后果
gs-accessing-data-neo4j/complete。
从 Spring Initializr 开始
您能够应用这个事后初始化的我的项目并单击 Generate 下载 ZIP 文件。此我的项目配置为适宜本教程中的示例。
手动初始化我的项目:
导航到https://start.spring.io。该服务提取应用程序所需的所有依赖项,并为您实现大部分设置。
抉择 Gradle 或 Maven 以及您要应用的语言。本指南假设您抉择了 Java。
单击Dependencies并抉择Spring Data Neo4j。
单击生成。
下载生成的 ZIP 文件,该文件是依据您的抉择配置的 Web 应用程序的存档。
如果您的 IDE 具备 Spring Initializr 集成,您能够从您的 IDE 实现此过程。
你也能够从 Github 上 fork 我的项目并在你的 IDE 或其余编辑器中关上它。
建设 Neo4j 服务器
在构建此应用程序之前,您须要设置 Neo4j 服务器。
Neo4j 有一个开源服务器,您能够收费装置。
在装置了 Homebrew 的 Mac 上,运行以下命令:
$酿造装置neo4j
无关其余选项,请拜访
https://neo4j.com/download/co...。
装置后,通过运行以下命令以默认设置启动它:
$ neo4j 开始
您应该会看到相似于以下内容的输入:
启动 Neo4j。
启动 neo4j (pid 96416)。默认状况下,它位于 http://localhost:7474/
在服务器筹备好之前可能会有短暂的提早。
无关以后状态,请参见 /usr/local/Cellar/neo4j/3.0.6/libexec/logs/neo4j.log。
默认状况下,Neo4j 的用户名和明码为neo4jand neo4j。然而,它须要更改新的帐户明码。为此,请运行以下命令:
curl -v -u neo4j:neo4j POST localhost:7474/user/neo4j/password -H "Content-type:application/json" -d "{\"password\":\"secret\"}"
这会将明码从 更改neo4j为secret - 在生产中不要做的事件!实现该步骤后,您应该筹备好运行本指南的其余部分。
定义一个简略的实体
Neo4j 捕捉实体及其关系,这两个方面等同重要。设想一下,您正在为一个零碎建模,您在其中存储每个人的记录。然而,您还想跟踪一个人的共事(teammates在本例中)。应用 Spring Data Neo4j,您能够应用一些简略的正文来捕捉所有这些,如以下清单(in 中
src/main/java/com/example/accessingdataneo4j/Person.java)所示:
package com.example.accessingdataneo4j;
import java.util.Collections;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
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.GeneratedValue;
@Node
public class Person {
@Id @GeneratedValue private Long id;
private String name;
private Person() {
// Empty constructor required as of Neo4j API 2.0.5
};
public Person(String name) {
this.name = name;
}
/**
- Neo4j doesn't REALLY have bi-directional relationships. It just means when querying
- to ignore the direction of the relationship.
- https://dzone.com/articles/mo...
*/
@Relationship(type = "TEAMMATE")
public Set<Person> teammates;
public void worksWith(Person person) {
if (teammates == null) { teammates = new HashSet<>();}teammates.add(person);
}
public String toString() {
return this.name + "'s teammates => " + Optional.ofNullable(this.teammates).orElse( Collections.emptySet()).stream() .map(Person::getName) .collect(Collectors.toList());
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
在这里,您有一个Person只有一个属性的类:name.
该类Person用 正文@NodeEntity。Neo4j 存储它时,会创立一个新节点。这个类也有一个id标记@GraphId。Neo4j@GraphId在外部应用来跟踪数据。
下一个重要的局部是teammates. 它很简略Set<Person>,但被标记为@Relationship。这意味着这个汇合的每个成员都应该作为一个独自的Person节点存在。留神方向是如何设置的UNDIRECTED。这意味着当您查问TEAMMATE关系时,Spring Data Neo4j 会疏忽关系的方向。
应用该worksWith()办法,您能够轻松地将人们分割在一起。
最初,您有一个不便的toString()办法能够打印出该人的姓名和该人的共事。
创立简略查问
Spring Data Neo4j 专一于在 Neo4j 中存储数据。但它继承了 Spring Data Commons 我的项目的性能,包含派生查问的能力。实质上,您不须要学习 Neo4j 的查询语言。相同,您能够编写一些办法并让查问为您编写。
要理解其工作原理,请创立一个查问Person节点的接口。以下清单 (in
src/main/java/com/example/accessingdataneo4j/PersonRepository.java) 显示了这样一个查问:
package com.example.accessingdataneo4j;
import java.util.List;
import org.springframework.data.neo4j.repository.Neo4jRepository;
public interface PersonRepository extends Neo4jRepository<Person, Long> {
Person findByName(String name);
List<Person> findByTeammatesName(String name);
}
PersonRepository扩大Neo4jRepository接口并插入其操作的类型:Person. 该接口带有许多操作,包含规范的 CRUD(创立、读取、更新和删除)操作。
然而您能够通过申明它们的办法签名来定义其余查问。在这种状况下,您增加了findByName,它会查找类型节点Person并找到与 上匹配的节点name。您还有findByTeammatesName,它会寻找一个Person节点,深刻到teammates字段的每个条目,并依据队友的name.
拜访 Neo4j 的权限
Neo4j 社区版须要凭据能力拜访它。您能够通过设置几个属性(在 中
src/main/resources/application.properties)来配置这些凭据,如以下清单所示:
spring.neo4j.uri=bolt://localhost:7687
spring.data.neo4j.username=neo4j
spring.data.neo4j.password=secret
这包含默认用户名 ( neo4j) 和咱们之前抉择的新设置的明码 ( secret)。
不要将实在凭据存储在您的源存储库中。相同,应用Spring Boot 的 property overrides在运行时配置它们。
创立应用程序类
Spring Initializr 为应用程序创立一个简略的类。以下清单显示了 Initializr 为本示例创立的类(在 中
src/main/java/com/example/accessingdataneo4j/AccessingDataNeo4jApplication.java):
package com.example.accessingdataneo4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class AccessingDataNeo4jApplication {
public static void main(String[] args) {
SpringApplication.run(AccessingDataNeo4jApplication.class, args);
}
}
@SpringBootApplication是一个不便的正文,它增加了以下所有内容:
@Configuration: 将类标记为应用程序上下文的 bean 定义源。
@EnableAutoConfiguration:通知 Spring Boot 依据类门路设置、其余 bean 和各种属性设置开始增加 bean。例如,如果spring-webmvc位于类门路上,则此正文将应用程序标记为 Web 应用程序并激活要害行为,例如设置DispatcherServlet.
@ComponentScan: 通知 Spring 在包中查找其余组件、配置和服务com/example,让它找到控制器。
该main()办法应用 Spring Boot 的SpringApplication.run()办法来启动应用程序。您是否留神到没有一行 XML?也没有web.xml文件。这个 Web 应用程序是 100% 纯 Java,您不用解决任何管道或基础设施的配置。
只有它们蕴含在@SpringBootApplication类的同一个包(或子包)中,Spring Boot 就会主动解决这些存储库。为了更好地管制注册过程,您能够应用@EnableNeo4jRepositories正文。
默认状况下,@EnableNeo4jRepositories扫描以后包以查找扩大 Spring Data 存储库接口之一的任何接口。basePackageClasses=MyRepository.class如果您的我的项目布局有多个我的项目并且找不到您的存储库,您能够应用它来平安地通知 Spring Data Neo4j 按类型扫描不同的根包。
显示记录输入。该服务应在几秒钟内启动并运行。
PersonRepository当初主动拆卸您之前定义的实例。Spring Data Neo4j 动静实现该接口并插入所需的查问代码以满足接口的任务。
该main办法应用 Spring BootSpringApplication.run()启动应用程序并调用CommandLineRunner构建关系的办法。
在本例中,您将创立三个本地Person实例:Greg、Roy 和 Craig。最后,它们只存在于内存中。请留神,没有人是任何人的队友(目前)。
起初,你找到 Greg,表明他与 Roy 和 Craig 单干,而后再次保持他。请记住,队友关系被标记为UNDIRECTED(即双向)。这意味着 Roy 和 Craig 也已更新。
这就是为什么当您须要更新 Roy 时。首先从 Neo4j 获取该记录至关重要。在将 Craig 增加到列表之前,您须要理解 Roy 队友的最新状态。
为什么没有代码能够获取 Craig 并增加任何关系?因为你曾经领有了!格雷格早些时候将克雷格标记为队友,罗伊也是如此。这意味着无需再次更新 Craig 的关系。当您遍历每个团队成员并将他们的信息打印到控制台时,您能够看到它。
最初,查看您向后看的其余查问,答复“谁与谁一起工作?”的问题。
以下清单显示了实现的
AccessingDataNeo4jApplication类 (at
src/main/java/com/example/accessingdataneo4j/AccessingDataNeo4jApplication.java):
package com.example.accessingdataneo4j;
import java.util.Arrays;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.data.neo4j.repository.config.EnableNeo4jRepositories;
@SpringBootApplication
@EnableNeo4jRepositories
public class AccessingDataNeo4jApplication {
private final static Logger log = LoggerFactory.getLogger(AccessingDataNeo4jApplication.class);public static void main(String[] args) throws Exception { SpringApplication.run(AccessingDataNeo4jApplication.class, args); System.exit(0);}@BeanCommandLineRunner demo(PersonRepository personRepository) { return args -> { personRepository.deleteAll(); Person greg = new Person("Greg"); Person roy = new Person("Roy"); Person craig = new Person("Craig"); List<Person> team = Arrays.asList(greg, roy, craig); log.info("Before linking up with Neo4j..."); team.stream().forEach(person -> log.info("\t" + person.toString())); personRepository.save(greg); personRepository.save(roy); personRepository.save(craig); greg = personRepository.findByName(greg.getName()); greg.worksWith(roy); greg.worksWith(craig); personRepository.save(greg); roy = personRepository.findByName(roy.getName()); roy.worksWith(craig); // We already know that roy works with greg personRepository.save(roy); // We already know craig works with roy and greg log.info("Lookup each person by name..."); team.stream().forEach(person -> log.info( "\t" + personRepository.findByName(person.getName()).toString())); List<Person> teammates = personRepository.findByTeammatesName(greg.getName()); log.info("The following have Greg as a teammate..."); teammates.stream().forEach(person -> log.info("\t" + person.getName())); };}
}
构建一个可执行的 JAR
您能够应用 Gradle 或 Maven 从命令行运行应用程序。您还能够构建一个蕴含所有必要依赖项、类和资源的单个可执行 JAR 文件并运行它。构建可执行 jar 能够在整个开发生命周期、跨不同环境等中轻松地将服务作为应用程序交付、版本化和部署。
如果您应用 Gradle,则能够应用./gradlew bootRun. 或者,您能够应用构建 JAR 文件./gradlew build,而后运行 JAR 文件,如下所示:
java -jar build/libs/gs-accessing-data-neo4j-0.1.0.jar
如果您应用 Maven,则能够应用./mvnw spring-boot:run. 或者,您能够应用构建 JAR 文件,./mvnw clean package而后运行该 JAR 文件,如下所示:
java -jar 指标/gs-accessing-data-neo4j-0.1.0.jar
此处形容的步骤创立了一个可运行的 JAR。您还能够构建经典的 WAR 文件。
您应该会看到相似于以下列表的内容(还有其余内容,例如查问):
在与 Neo4j 连贯之前...
格雷格的队友 => []罗伊的队友 => []克雷格的队友 => []
按姓名查找每个人...
格雷格的队友 => [罗伊,克雷格]罗伊的队友 => [格雷格,克雷格]克雷格的队友 => [罗伊,格雷格]
您能够从输入中看到(最后)没有人通过任何关系连贯。而后,在您增加人员后,他们被捆绑在一起。最初,您能够看到依据队友查找人员的便捷查问。
总结
祝贺!您刚刚设置了一个嵌入式 Neo4j 服务器,存储了一些简略的相干实体,并开发了一些疾速查问。