使用Spring Data Neo4j进行领域建模
人CI要求
我们将在这里简单地通过构建人员CI来开始。 出于各种原因而使人们进入CMDB很有用:它们使您可以定义细粒度的访问控制(例如,Jim可以将这样的应用程序部署到开发环境中; Eric可以将他想要的任何东西部署到他想要的任何地方;等等。 ); 它们使您可以定义将接收关键事件通知的组。 等等
我们的个人CI将有一个用户名,名字和姓氏,一些电话号码,一个电子邮件地址,一个经理,直接报告,最后是他或她工作的项目。 我们需要能够在列表视图中显示人员,在详细信息视图中显示给定人员,允许用户创建,编辑和删除人员等等。 例如,下面是列表视图的外观,至少现在是这样:
这是我们的详细信息视图的外观:
人与项目之间的关系具有关联的角色。 这种关系也是协作者列表的基础:如果至少有一个项目是他们两个成员,那么两个人就是协作者。
我们的简单要求应该足以显示编写Spring Data Neo4j代码的感觉。
创建人员和项目成员实体
首先,我们将创建人。 我已经取消了验证和JAXB批注,因为它们与我们当前的目的无关:
package org.skydingo.skybase.model;import java.util.Set;
import org.neo4j.graphdb.Direction;
import org.skydingo.skybase.model.relationship.ProjectMembership;
import org.springframework.data.neo4j.annotation.*;
import org.springframework.data.neo4j.support.index.IndexType;@NodeEntity
public class Person implements Comparable<Person> {@GraphId private Long id;@Indexed(indexType = IndexType.FULLTEXT, indexName = "searchByUsername")private String username;private String firstName, lastName, title, workPhone, mobilePhone, email;@RelatedTo(type = "REPORTS_TO")private Person manager;@RelatedTo(type = "REPORTS_TO", direction = Direction.INCOMING)private Set<Person> directReports;@RelatedToVia(type = "MEMBER_OF")private Set<ProjectMembership> memberships;public Long getId() { return id; }public void setId(Long id) { this.id = id; }public String getUsername() { return username; }public void setUsername(String username) { this.username = username; }... other accessor methods ...public Person getManager() { return manager; }public void setManager(Person manager) { this.manager = manager; }public Set<Person> getDirectReports() { return directReports; }public void setDirectReports(Set<Person> directReports) {this.directReports = directReports;}public Iterable<ProjectMembership> getMemberships() { return memberships; }public ProjectMembership memberOf(Project project, String role) {ProjectMembership membership = new ProjectMembership(this, project, role);memberships.add(membership);return membership;}... equals(), hashCode(), compareTo() ...
}
我们使用许多注释来放置结构。 让我们从节点及其属性开始。 然后,我们将研究节点之间的简单关系。 然后,我们看一下所谓的关系实体,它们基本上是奇特的关系。 首先,这是我们的域模型的抽象表示:
现在让我们看一些细节。
节点及其属性 。 当我们有一个节点支持的实体时,首先我们用@NodeEntity注释对其进行注释。 大多数简单的节点属性(即与其他节点没有关系的属性)都会随处可见。 请注意,我不必注释firstName,lastName,email等。 Spring Data Neo4j将在那里自动处理映射。
但是有两个例外。 第一个是我将@GraphId放在我的id属性上。 这告诉Spring Data Neo4j这是一个我们可以用于查找的标识符。 另一个是@Indexed注释,该注释(惊奇)为所讨论的属性创建了一个索引。 当您想要替代基于ID的查找时,这很有用。
现在我们来看一下关系。 概括地说,有简单的关系和更高级的关系。 我们将从简单的开始。
简单的关系 。 从低层次上来说,Neo4j是一个图形数据库,因此我们可以用图形理论术语来讨论图形,例如节点,边,有向边,DAG等。 但是这里我们使用图进行领域建模,因此我们根据更高层次的领域建模概念来解释低层次的图形概念。 Spring Data Neo4j使用的语言是“节点实体”代表节点,“关系”代表边缘。
我们的Person CI有一个简单的关系,称为REPORTS_TO,它与人们相关联,因此我们可以对报告层次结构进行建模。 Person有两个用于此关系的字段:manager和directReports。 这些是具有相同关系的相对站点。 我们使用@RelatedTo(type =“ REPORTS_TO”)注释这些字段。 注释还具有一个direction元素,其默认值为Direction.OUTGOING,这意味着“此”节点为边缘尾部。 这就是为什么我们为directReports字段明确指定direction = Direction.INCOMING的原因。
这在数据库中是什么样的? Neoclipse揭示了一切。 以下是一些报告关系示例(单击图像可查看大图):
(小写:有一个@Fetch注释-我们待会儿会看到它-告诉Spring Data Neo4j渴望加载相关实体。出于某种原因,我不必在管理器和直接报表关系中使用它,我不知道为什么。如果有人知道,我将不胜感激。
关系实体 。 除了人与人之间的REPORTS_TO关系之外,我们还关心人与项目之间的MEMBER_OF关系。 这比REPORTS_TO关系更有趣,因为MEMBER_OF具有关联的属性-角色-类似于向RDBMS中的链接表添加列,正如我在上一篇文章对Brig的答复中提到的那样。 Person.memberOf()方法提供了一种使用特殊ProjectMembership“关系实体”将人员分配到项目的便捷方法。 这是代码:
package org.skydingo.skybase.model.relationship;import org.skydingo.skybase.model.Person;
import org.skydingo.skybase.model.Project;
import org.springframework.data.neo4j.annotation.*;@RelationshipEntity(type = "MEMBER_OF")
public class ProjectMembership {@GraphId private Long id;@Fetch @StartNode private Person person;@Fetch @EndNode private Project project;private String role;public ProjectMembership() { }public ProjectMembership(Person person, Project project, String role) {this.person = person;this.project = project;this.role = role;}public Person getPerson() { return person; }public void setPerson(Person person) { this.person = person; }public Project getProject() { return project; }public void setProject(Project project) { this.project = project; }public String getRole() { return role; }public void setRole(String role) { this.role = role; }... equals(), hashCode(), toString() ...}
像Person一样,ProjectMembership是一个实体,但它是一个关系实体。 我们使用@RelationshipEntity(type =“ MEMBER_OF”)将其标记为关系实体,并且与Person一样,将@GraphId用作id属性。 @StartNode和@EndNode注释分别指示边缘的尾部和头部。 @Fetch告诉Spring Data Neo4j急切地加载节点。 默认情况下,Spring Data Neo4j不会急于加载关系,因为可能会将整个图形加载到内存中。
创建人仓库
这是我们的PersonRepository接口:
package org.skydingo.skybase.repository;import java.util.Set;
import org.skydingo.skybase.model.Person;
import org.skydingo.skybase.model.Project;
import org.springframework.data.neo4j.annotation.Query;
import org.springframework.data.neo4j.repository.GraphRepository;public interface PersonRepository extends GraphRepository<Person> {Person findByUsername(String username);@Query("start project=node({0}) match project<--person return person")Set<Person> findByProject(Project project);@Query("start person=node({0}) " +"match person-[:MEMBER_OF]->project<-[:MEMBER_OF]-collaborator " +"return collaborator")Set<Person> findCollaborators(Person person);
}
我在上一篇文章中指出,我们需要做的就是扩展GraphRepository接口。 Spring Data自动生成实现。
对于findByUsername(),Spring Data可以找出所需的查询。 对于其他两个查询,我们使用@Query和Cypher查询语言来指定所需的结果集。 查询中的{0}指的是finder方法参数。 在findCollaborators()查询中,我们使用[:MEMBER_OF]指示我们要遵循的关系。 这些返回Set而不是Iterables以消除重复项。
创建网页控制器
我们不会在这里介绍整个控制器,但是会介绍一些代表性的方法。 假设我们已经将一个PersonRepository注入到控制器中。
创建一个人 。 要创建一个人,我们可以使用以下方法:
@RequestMapping(value = "", method = RequestMethod.POST)
public String createPerson(Model model, @ModelAttribute Person person) {personRepo.save(person);return "redirect:/people?a=created";
}
再一次,我们忽略了验证。 我们要做的就是在存储库上调用save()方法。 这也是更新的工作方式。
寻找所有人 。 接下来,这是我们如何吸引所有人的方法:
@RequestMapping(value = "", method = RequestMethod.GET)
public String getPersonList(Model model) {Iterable<Person> personIt = personRepo.findAll();List<Person> people =new ArrayList<Person>(IteratorUtil.asCollection(personIt));Collections.sort(people);model.addAttribute(people);return "personList";
}
我们必须做一些工作才能使PersonRepository.findAll()返回的Iterable成为所需的格式。 Neo4j(org.neo4j.helpers.collection.IteratorUtil)随附的IteratorUtil在此提供帮助。
寻找一个人 。 在这里,我们要显示我们上面建立的个人详细信息。 与findAll()一样,我们必须做一些自我按摩:
@RequestMapping(value = "/{username}", method = RequestMethod.GET)
public String getPersonDetails(@PathVariable String username, Model model) {Person person = personRepo.findByUsername(username);List<ProjectMembership> memberships =CollectionsUtil.asList(person.getMemberships());List<Person> directReports =CollectionsUtil.asList(person.getDirectReports());List<Person> collaborators =CollectionsUtil.asList(personRepo.findCollaborators(person));Collections.sort(directReports);Collections.sort(collaborators);model.addAttribute(person);model.addAttribute("memberships", memberships);model.addAttribute("directReports", directReports);model.addAttribute("collaborators", collaborators);return "personDetails";
}
如果要查看JSP,请访问Skybase GitHub网站 。
配置APP
最后,这是我的beans-service.xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:context="http://www.springframework.org/schema/context"xmlns:neo4j="http://www.springframework.org/schema/data/neo4j"xmlns:p="http://www.springframework.org/schema/p"xmlns:tx="http://www.springframework.org/schema/tx"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-3.0.xsdhttp://www.springframework.org/schema/data/neo4jhttp://www.springframework.org/schema/data/neo4j/spring-neo4j-2.0.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-3.0.xsd"><context:property-placeholderlocation="classpath:/spring/environment.properties" /><context:annotation-config /><context:component-scan base-package="org.skydingo.skybase.service" /><tx:annotation-driven mode="proxy" /><neo4j:config storeDirectory="${graphDb.dir}" /><neo4j:repositories base-package="org.skydingo.skybase.repository" />
</beans>
Neo4j具有一个基于POJO的基本映射模型和一个基于AspectJ的高级映射模型。 在此博客文章中,我们一直在使用基于POJO的基本方法,因此我们不需要包括与AspectJ相关的配置,例如<context:spring-configured>。
在那里,这就是Neo4j支持的Person CI。 编码愉快!
要更详细地查看代码或参与Skybase开发,请访问Skybase GitHub网站 。
参考:来自Skydingo博客的JCG合作伙伴 Willie Wheeler的Spring Data Neo4j进行领域建模 。
相关文章 :
- Spring Data JPA的持久层
- 基于事务的基于事件的NOSQL存储
- SQL或NOSQL:这是问题吗?
- 什么是NoSQL?
- Cassandra,MongoDB,CouchDB,Redis,Riak,HBase比较
翻译自: https://www.javacodegeeks.com/2012/01/domain-modeling-with-spring-data-neo4j.html
使用Spring Data Neo4j进行领域建模相关推荐
- 通过Spring Data Neo4J操作您的图形数据库
在前面的一篇文章<图形数据库Neo4J简介>中,我们已经对其内部所使用的各种机制进行了简单地介绍.而在我们尝试对Neo4J进行大版本升级时,我发现网络上并没有任何成型的样例代码以及简介,而 ...
- java连接neo4j(使用spring data neo4j)
1. Spring Data Neo4j概述 认识Spring-Data-Neo4j之前,需要先对OGM有一个了解 OGM即对象图映射(Object Graph Mapper ,简称ORM ),基于O ...
- Spring认证中国教育管理中心-Spring Data Neo4j教程一
原标题:Spring认证中国教育管理中心-Spring Data Neo4j教程一(Spring中国教育管理中心) 5. 开始 我们为 SDN 提供了 Spring Boot 启动器.请通过您的依赖管 ...
- Spring认证中国教育管理中心-Spring Data Neo4j教程三
原标题:Spring认证中国教育管理中心-Spring Data Neo4j教程三(Spring中国教育管理中心) 6.2.处理和提供唯一 ID 6.2.1.使用内部 Neo4j id 为您的域类提供 ...
- Spring Data Neo4j
问题 使用响应式编程方式来访问Neo4j,这里假设已经准备好Neo4j服务器了. Spring Initializr https://start.spring.io/ 在这个界面初始化工程: appl ...
- Spring Data Neo4j解除两个节点之间的关系
问题 需要解除两个Node之间的某种关系 思路 利用@Query注解,在其中运行Cypher的解除两个Node之间关系语句即可. Repository @Query("MATCH (:MyN ...
- Spring Data JPA例子[基于Spring Boot、Mysql]
关于Spring Data Spring社区的一个顶级工程,主要用于简化数据(关系型&非关系型)访问,如果我们使用Spring Data来开发程序的话,那么可以省去很多低级别的数据访问操作,如 ...
- Spring Data 发布更改版本管理方案之后的第一个版本:2020.0.0
点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 2020年10月28日 Spring Data自更改版本 ...
- 01 | Spring Data JPA 初识
课程正式开始了,这里我会以一个案例的形式来和你讲解如何通过 Spring Boot 结合 Spring Data JPA 快速启动一个项目.如何使用 UserRepository 完成对 User 表 ...
最新文章
- linux 服务管理两种方式service和systemctl
- 合并html文件工具,整合 DevTools 和 Chrome
- 基于 flyweight 的格式化文本处理的 Boost.Flyweight 示例
- python数据接口获取数据_python UI自动化实战记录二:请求接口数据并提取数据
- c++调用cplex求解例子_视频教程 | 用Python玩转运筹优化求解器IBM CPLEX(二)
- cba篮球暂停次数和时间_为什么足球赛的观赏性比篮球更强?这三点是主要原因...
- json:JSONObject包的具体使用(JSONObject-lib包是一个beans,collections,maps,java arrays和xml和JSON互相转换的包)...
- 海南省重点公共场所WiFi覆盖率达到97.7%
- Spring源码解析一(框架梳理)
- Fiddler对安卓模拟器里的APP抓包(步骤详细,各种抓包工具总结)
- SpringBoot项目从IE浏览器跳转至谷歌浏览器并打包成windows环境下可行EXE文件
- [java编程题]打印指定年指定月份的日历
- 自动驾驶笔记-轨迹跟踪-综述
- 什么是「重置SMC、NVRAM、PRAM」?看完这篇文章你就懂了!
- HTML的head,头头头头!!!
- java中ioc作用_Spring中的IOC是什么意思,为什么要用IOC而不是New来创建实例?
- 【PyG】图神经网络GAT代码自学
- 3dmax:3dmax三维VR渲染设置之高级灯光渲染(经典案例—利用自由聚光灯制作筒灯效果效果)图文教程
- AF base tuning <0>
- JDK API(SE8)(部分System,Math,Integer类)
热门文章
- 记录一下SpringCloud-Gateway使用lb动态路由遇到的坑
- 三思笔记_使用反射前先三思
- cassandra使用心得_使用Spring Data Cassandra缓存的预备语句
- switch字符串jdk_应用新的JDK 11字符串方法
- jmeter 采样器作用_实施自定义JMeter采样器
- pcl_openmap_OpenMap教程–第1部分
- Java EE 8怎么了? (第2部分)
- AWS Loft的数据库周
- intellij注释模板_IntelliJ中的实时模板
- ElasticSearch-Hadoop:从Hadoop到ElasticSearch索引产品视图计数和客户顶部搜索查询