SpringBoot使用Neo4j

1.Neo4j简介

Neo4j是一个高性能的,NOSQL图形数据库,它将结构化数据存储在网络上而不是表中。它是一个嵌入式的、基于磁盘的、具备完全的事务特性的Java持久化引擎,但是它将结构化数据存储在网络(从数学角度叫做图)上而不是表中。Neo4j也可以被看作是一个高性能的图引擎,该引擎具有成熟数据库的所有特性。程序员工作在一个面向对象的、灵活的网络结构下而不是严格、静态的表中——但是他们可以享受到具备完全的事务特性、企业级的数据库的所有好处。

Neo4j的官方网站:http://www.neo4j.org

2.安装Neo4j

网上安装教程很多,本文是在mac电脑下使用docker+Kitematic安装的,步骤大致如下:

1.启动docker
2.在Kitematic中搜索Neo4j镜像并安装,这里安利一下这个软件,安装一些镜像非常方便,如下图:

wechatimg13.png

3.安装完成后,访问对应web地址,如下:

wechatimg13.png

3.SpringBoot整合

接下来介绍SpringBoot中如何视同Neo4j。

3.1 添加Neo4j依赖

创建项目,pom文件中引入依赖,如下:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-neo4j</artifactId>
</dependency>

3.2 配置文件

在配置文件中配置Neo4j相关配置,如下:

# neo4j配置
spring.data.neo4j.uri= bolt://localhost:7687
spring.data.neo4j.username=neo4j
spring.data.neo4j.password=neo4j

3.3 创建对应entity

这里以部门为例,要创建一个如下的图:

     * CEO
     *    -设计部
     *        - 设计1组
     *        - 设计2组
     *    -技术部
     *        - 前端技术部
     *        - 后端技术部
     *        - 测试技术部

那么这里简单创建一个部门实体和一个关系实体。

其中部门实体,如下:

@NodeEntity(label = "dept")
@Data
@Builder
public class Dept {

    @Id
    @GeneratedValue
    private Long id;

    @Property(name = "deptName")
    private String deptName;

}

关系实体如下:

@RelationshipEntity(type = "relationShip")
@Data
@Builder
public class RelationShip {

    @Id
    @GeneratedValue
    private Long id;

    @StartNode
    private Dept parent;

    @EndNode
    private Dept child;
}

这里说明一下几个注解的意思:

  • @NodeEntity:标明是一个节点实体
  • @RelationshipEntity:标明是一个关系实体
  • @Id:实体主键
  • @Property:实体属性
  • @GeneratedValue:实体属性值自增
  • @StartNode:开始节点(可以理解为父节点)
  • @EndNode:结束节点(可以理解为子节点)

3.4 repository

由于使用的spring-data操作neo4j,所以实现逻辑类似,创建接口继承Neo4jRepository。

DeptRepository如下:

import org.springframework.data.neo4j.repository.Neo4jRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface DeptRepository extends Neo4jRepository<Dept,Long> {

}

RelationShipRepository如下:

import org.springframework.data.neo4j.repository.Neo4jRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface RelationShipRepository extends Neo4jRepository<RelationShip, Long> {

}

3.5 基本使用

这里创建了一些基础方法,使用方式和spring-data-jpa类似,由于需要构建一个本文3.1所描述的图,所以创建了一个create方法来初始化数据,完整代码如下:

@RestController
public class TestController {

    @Resource
    private DeptRepository deptRepository;
    @Resource
    private RelationShipRepository relationShipRepository;

    /**
     * CEO
     *    -设计部
     *        - 设计1组
     *        - 设计2组
     *    -技术部
     *        - 前端技术部
     *        - 后端技术部
     *        - 测试技术部
     */
    @GetMapping("create")
    public void create(){
        Dept CEO = Dept.builder().deptName("CEO").build();
        Dept dept1 = Dept.builder().deptName("设计部").build();
        Dept dept11 = Dept.builder().deptName("设计1组").build();
        Dept dept12 = Dept.builder().deptName("设计2组").build();

        Dept dept2 = Dept.builder().deptName("技术部").build();
        Dept dept21 = Dept.builder().deptName("前端技术部").build();
        Dept dept22 = Dept.builder().deptName("后端技术部").build();
        Dept dept23 = Dept.builder().deptName("测试技术部").build();
        List<Dept> depts = new ArrayList<>(Arrays.asList(CEO,dept1,dept11,dept12,dept2,dept21,dept22,dept23));
        deptRepository.saveAll(depts);

        RelationShip relationShip1 = RelationShip.builder().parent(CEO).child(dept1).build();
        RelationShip relationShip2 = RelationShip.builder().parent(CEO).child(dept2).build();
        RelationShip relationShip3 = RelationShip.builder().parent(dept1).child(dept11).build();
        RelationShip relationShip4 = RelationShip.builder().parent(dept1).child(dept12).build();
        RelationShip relationShip5 = RelationShip.builder().parent(dept2).child(dept21).build();
        RelationShip relationShip6 = RelationShip.builder().parent(dept2).child(dept22).build();
        RelationShip relationShip7 = RelationShip.builder().parent(dept2).child(dept23).build();
        List<RelationShip> relationShips = new ArrayList<>(Arrays.asList(relationShip1,relationShip2,relationShip3,relationShip4,relationShip5
                ,relationShip6,relationShip7));
        relationShipRepository.saveAll(relationShips);
    }

    @GetMapping("get")
    public RelationShip get(Long id){
        Optional<RelationShip> byId = relationShipRepository.findById(id);
        return byId.orElse(null);
    }

    @GetMapping("deleteRelationShip")
    public void deleteRelationShip(Long id){
        relationShipRepository.deleteById(id);
    }

    @GetMapping("deleteDept")
    public void deleteDept(Long id){
        deptRepository.deleteById(id);
    }

    @GetMapping("deleteAll")
    public void deleteAll(){
        deptRepository.deleteAll();
        relationShipRepository.deleteAll();
    }
}

执行create方法初始化数据,结果如下图所示:

wechatimg13.png

其余测试方法这里就不在演示了,可以自行测试。

4.Neo4j基本命令

4.1 操作命令简介

接下来介绍一下Neo4j的基本操作命令。

  • CREATE命令:创建节点命令
  • MATCH命令:查询命令
  • RETURN命令:返回数据命令
  • DELETE命令:删除命令,可以用于删除节点和关联节点信息
  • REMOVE命令:可以用于删除标签和属性

4.2 简单练习

创建命令,可以用来创建节点和关系节点,比如我们要在创建一个部门,秘书部,如下,执行如下命令:

CREATE (d:dept {deptName:"秘书部"})

操作后如下图所示:

wechatimg13.png

目前可以看到,秘书部和其余节点是没有关系的,那么接下来将秘书部与CEO创建关系,执行如下命令:

MATCH (n:dept {deptName:"CEO"}),(m:dept {deptName:"秘书部"}) CREATE (n)-[r:relationShip]->(m) return r;

查看结果如图:

wechatimg13.png

可以看到秘书部已经挂在了CEO节点下。

其中从上面就可以看出,CQL语句大致结构如下:

  • MATCH RETURN:查询命中结果返回;
  • MATCH CREATE RETURN:查询后创建关系返回;
  • MATCH DELETE:查询命中删除;

...

5.源码

源码地址:https://gitee.com/dalaoyang/springboot_learn/tree/master/springboot2_neo4j

6.参考

参考地址:

https://baike.baidu.com/item/Neo4j/9952114?fr=aladdin
http://www.neo4j.org

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,928评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,192评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,468评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,186评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,295评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,374评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,403评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,186评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,610评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,906评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,075评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,755评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,393评论 3 320
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,079评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,313评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,934评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,963评论 2 351

推荐阅读更多精彩内容