使用Spring Data Neo4j進行領域建模

大家好,威利在這里。 上次我告訴您,我正在使用Neo4j和Spring Data Neo4j構建Skybase CMDB,我很高興收到很多對此的積極反饋。 我展示了一些代碼,但沒有那么多。 在本文中,我將向您展示如何使用Spring Data Neo4j在Skybase中構建人員配置項 (CI)。

人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

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/374509.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/374509.shtml
英文地址,請注明出處:http://en.pswp.cn/news/374509.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

mysql 阿里內核人員

丁奇 http://dinglin.javaeye.com/鳴嵩 曹偉-鳴嵩 (新浪微博)彭立勛 http://www.penglixun.com/皓庭 http://wqtn22.iteye.com/項仲 http://blog.csdn.net/wudongxu劍川 http://gaoyusong.com/武藏 http://ybbct.iteye.com/祁奚 http://i.mtime.com/844165/褚霸 http://blog.y…

linux基本命令學習

1. 執行文件&#xff1a; ./文件 &#xff1a;執行該文件 sh startup.sh 執行該文件 2. Vi編輯 vi命令&#xff1a; :w 保存文件但不退出 :w file 將修改另外保存到file中&#xff0c;不退出 :w! 強制保存&#xff0c;不推出 :wq 保存文件并退出 :wq! 強制保存文件&#xff0…

506. 相對名次

方法一 復制數組排序返回對應下標 class Solution {public String[] findRelativeRanks(int[] score) {int n score.length;int[] newScore Arrays.copyOf(score,n);Arrays.sort(newScore);String[] res new String[n];for(int i 0;i<n;i){int rank Arrays.binarySear…

Java壓縮

在最近的項目中&#xff0c;我們不得不做一些我個人從未真正看過的事情。 壓縮。 我們需要拍幾個文件和圖像&#xff0c;將它們壓縮并提供給FTP使用&#xff0c;是的&#xff0c;總有一天&#xff0c;感覺確實回到了90年代。 除了過去的FTP之行外&#xff0c;它還是一個很好的機…

蘇州面對公司發布

假設您對我們這種創業型公司和我們的發展方向感興趣的話&#xff0c;我們希望通過以下10個問答進一步添加兩方的了解。我們希望看到的是您經過深思熟慮的、對公司和自己的前途負責任的謹慎回答。而不是應付公差式的輕描淡寫&#xff08;我們會依據您回答質量的高低決定是否邀請…

linux多線程_Java+Linux,深入內核源碼講解多線程之進程

之前寫了兩篇文章&#xff0c;都是針對Linux這個系統的&#xff0c;為什么?我為什么這么喜歡寫這個系統的知識&#xff0c;可能就是為了今天的內容多線程系列&#xff0c;現在多線程不是一個面試重點 啊&#xff0c;那如果你能深入系統內核回答這個知識點&#xff0c;面試官會…

594. 最長和諧子序列

和諧數組是指一個數組里元素的最大值和最小值之間的差別 正好是 1 。 現在&#xff0c;給你一個整數數組 nums &#xff0c;請你在所有可能的子序列中找到最長的和諧子序列的長度。 數組的子序列是一個由數組派生出來的序列&#xff0c;它可以通過刪除一些元素或不刪除元素、…

解決git clone報錯SSL certificate problem

Git新手一枚&#xff0c;今天進行git clone操作時發生如下問題&#xff1a;提示無效的鏈接error: SSL certificate problem: Invalid certificate chain while accessing https://githib.com/...XXXX.git fatal: HTTP request failed解決方法也很簡單&#xff0c;一條命令就搞定…

使用內存映射文件獲取巨大的矩陣

總覽 矩陣可能真的很大&#xff0c;有時甚至比一個數組中可以容納的更大。 您可以通過具有多個數組來擴展最大大小&#xff0c;但這會使堆大小確實很大且效率低下。 一種替代方法是在內存映射文件上使用包裝器。 內存映射文件的優點是它們對堆的影響很小&#xff0c;并且可以由…

ipad連接電腦_這些應用讓iPad生產力分分鐘UP

IT時報見習記者 錢奕昀用iPad辦公這件事&#xff0c;多年前網友就在討論&#xff0c;最常見的還是那句“買前生產力&#xff0c;買后愛奇藝”。很長一段時間里&#xff0c;它的生產力屬性都是弱于娛樂屬性的。其實&#xff0c;作為PC端和移動端的形態中和&#xff0c;iPad可以…

Mac OSX 快捷鍵命令行

ctrlshift 快速放大dock的圖標會暫時放大&#xff0c;而如果你開啟了dock放大CommandOptionW 將所有窗口關閉CommandW 將當前窗口關閉(可以關閉Safari標簽欄,很實用) CommandOptionM …

將JavaFX 2.0與Swing和SWT集成

JavaFX 2.0對JavaFX的改進之一是可以更輕松地與Swing和SWT進行互操作 。 一些在線資源記錄了如何完成此操作。 其中包括將JavaFX集成到Swing應用程序和SWT Interop中 。 但是&#xff0c;在有效的類級Javadoc文檔的一個很好的示例中&#xff0c;各自的JavaFX類javafx.embed.swi…

iOS-如何返回某個字符串的拼音助記碼

我也是看了網上的一個示例代碼后&#xff0c;在它的基礎上進行的修改。因為項目上會用到&#xff0c;我相信很多人的項目上也會用到。所以實現后&#xff0c;也趕緊分享出來&#xff0c;希望后來人不需要花費時間了。 提示&#xff1a;這里用到了正則表達式&#xff0c;使用了一…

wifi rssi 計算 距離_WiFi和WLAN是一樣的?真相在這里~別再傻傻分不清了

我們通常上網的時候會說連接WiFi如果注意到無線網絡的名稱就會發現手機的連接顯示是WLAN別再將WiFI和WLAN搞混了&#xff01;二者的定義WLANWLAN的全稱為 Wireless Local Area Networks,中文意思為無線局域網絡&#xff0c;是一種數據傳輸系統。它是利用射頻技術進行數據傳輸&a…

【Shell劇本練習】得出的結論是當前用戶

推斷是否當前用戶root。假設是暗示root用戶&#xff0c;假設而不是提示對于普通用戶#!/bin/bash #title: testus.sh #author: orangleliu #date: 2014-08-09 #desc: get current user, if it is root user, tell us it is super user or tell us is a common user# #Function C…

播放框架模塊:分而治之

通常情況是您開始開發應用程序并繼續滿足要求。 當您的應用程序變得更大時&#xff0c;您開始意識到將其分為不同組件的便利。 而且&#xff0c;當您開發第二個或第三個應用程序時&#xff0c;您開始認識到可以在不同應用程序之間重用的某些功能。 這是模塊化應用程序的兩個很好…

Alpha階段項目總結

1.我們的軟件要解決什么問題&#xff1f;是否定義得很清楚&#xff1f;是否對典型用戶和典型場景有清晰的描述&#xff1f; 我們的軟件是一款針對健康飲食而做的一款飲食健康軟件&#xff0c;對生活中我們經常遲到的很多事物組合都進行了詳細的注解&#xff0c;用戶可以清楚地看…

實用的it知識學習_怎樣能更快更好的學習好書法?分享一些比較實用的理論知識...

如何能更快更高效的學習書法&#xff1f;首先了解一些書法理論知識是很有必要的&#xff01;它能讓你在學習書法的過程中不至于迷茫 &#xff01;能助你更快學好書法&#xff01;一、書論在實踐中產生我們大部分人都覺得學習書法可以沒有理論&#xff0c;但不可無技法。但理論和…

九度oj-1001-Java

題目描述&#xff1a; This time, you are supposed to find AB where A and B are two matrices, and then count the number of zero rows and columns. 輸入&#xff1a; The input consists of several test cases, each starts with a pair of positive integers M and N …

字節流與字符流的區別

最近在項目中遇到一個encoding的問題&#xff0c;記錄一下。 具體而言就是&#xff0c;項目中有A/B兩個部分&#xff0c;A部分由我們負責&#xff0c;Java實現&#xff1b;B部分是UK負責的&#xff0c;使用Delphi&#xff0c;A、B在交互時發送一個http請求&#xff0c; 請求匯總…