Neo4j整合Java
Neo4j安装及简单使用
Neo4j和图数据库简介
neo4j是基于Java语言编写图形数据库。图是一组节点和连接这些节点的关系。图形数据库也被称为图形数据库管理系统或GDBMS。
Neo4j的是一种流行的图形数据库。 其他的图形数据库是Oracle NoSQL数据库,OrientDB,HypherGraphDB,GraphBase,InfiniteGraph,AllegroGraph。
Neo4j图形数据库的主要构建块是:
-
节点:是图表的基本单位。 它包含具有键值对的属性
-
关系:连接两个节点,具有方向:单向和双向。每个关系包含“开始节点”或“从节点”和“到节点”或“结束节点”。关系也可以包含属性作为键值对。
-
属性:是用于描述图节点和关系的键值对。Key =值,其中Key是一个字符串,值可以通过使用任何Neo4j数据类型来表示
-
标签:将节点分组为集合。将一个公共名称与一组节点或关系相关联。 节点或关系可以包含一个或多个标签。 我们可以为现有节点或关系创建新标签。我们可以从现有节点或关系中删除现有标签。
-
数据浏览器:用于执行CQL命令并查看输出输出。
Neo4j安装
从官网下载最新版 Neo4j 社区版(Community),注意使用Neo4j需要安装java环境,我这里使用3.5.4版本,对应java1.8可以使用。
Neo4j-3.5.4 社区window版和java1.8,网盘资源获取,提取码me9t
下载后解压压缩包文件夹内容如下:
Neo4j应用程序有如下主要的目录结构:
-
bin目录:用于存储Neo4j的可执行程序;
-
conf目录:用于控制Neo4j启动的配置文件;
-
data目录:用于存储核心数据库文件;
-
plugins目录:用于存储Neo4j的插件;
配置环境变量
在计算机-属性中创建系统环境变量NEO4J_HOME,并把主目录(E:\Program Files (x86)\neo4j-community-3.4.0)设置为变量值。
NEO4J_HOME=E:\Program Files (x86)\neo4j-community-3.4.0
如果没有安装过java的环境,也需要配置java环境变量。
JAVA_HOME=E:\Program Files (x86)\jdk1.8.0_181
再在path中添加Neo4j和java安装目录下的bin文件夹。
%NEO4J_HOME%\bin。
%JAVA_HOME%\bin。
修改Neo4j配置文件
修改neo4j-community-3.5.25\conf下的neo4j.conf配置文件
去掉第54、71、75、79前面的#
# 允许远程访问
dbms.connectors.default_listen_address=0.0.0.0
# 开启bolt服务,默认端口7687
dbms.connector.bolt.listen_address=0.0.0.0:7687
# 开启http服务,默认端口7474
dbms.connector.http.listen_address=0.0.0.0:7474
# 开启https服务,默认端口7473
dbms.connector.https.listen_address=0.0.0.0:7473
Neo4j启动和停止
方法一:通过控制台启动Neo4j程序(win10建议使用)
CMD管理员身份运行(一定要以管理员身份进入CMD,否则会出现警告。警告: This command does not appear to be running with administrative rights. Some commands may fail e.g. Start/Stop)
输入:
neo4j.bat console
方法二:把Neo4j安装为服务(linux建议使用)
安装和卸载服务:
neo4j install-service
neo4j uninstall-service
启动服务,停止服务,重启服务和查询服务的状态:
neo4j start
neo4j stop
neo4j restart
neo4j status
在浏览器中打开http://localhost:7474 默认跳转到 http://localhost:7474/browser,出现Neo4j界面,则安装成功。初始密码:neo4j ,进去之后需要修改密码。
在这里插入图片描述
切换数据库
每次启动neo4j,它只能读取一个数据库。默认情况下的Graph.db数据库。
方法一:修改配置文件(win10)
使用Neo3.x创建新数据库而不删除现有数据库,所以只需在$NEO4J_HOME\conf的目录编辑neo4j.conf。搜寻dbms.active_database=,其默认值应为graph.db。用其他名称替换它,然后再次启动neo4j。现在,将在该目录名下创建一个新数据库。若要切换回以前的db,请重复这些步骤,只需将新值替换为graph.db在配置文件中。
注意:如果在neo4j启动的时候修改了配置文件,则需要重新启动一次,浏览器页面才会更新。
方法二:建立软连接(linux)
首次修改:
// 请将$NEO4j_HOME改为你的neo4j的安装路径
cd $NEO4j_HOME/data/databases/
// 保存原来数据库
mv graph.db graph1.db
//建立指向新数据库的软件接
ln -s graph2.db graph.db
//重启neo4j
cd $NEO4j_HOME/bin
./neo4j restart
再次修改
倘若我想访问graph3.db,就很简单了
//建立指向新数据库的软件接
ln -s graph3.db graph.db
//重启neo4j
cd $NEO4j_HOME/bin
./neo4j restart
Neo4j的CQL语句
CQL代表Cypher查询语言。 像Oracle数据库具有查询语言SQL,Neo4j具有CQL作为查询语言。
运行Neo4j之后,在软件窗口可以选择数据库创建位置,之后Neo4j就自动为我们创建好了数据库。
Neo4j CQL
- 它是Neo4j图形数据库的查询语言。
- 它是一种声明性模式匹配语言
- 它遵循SQL语法。
- 它的语法是非常简单且人性化、可读的格式。
我们可以通过Neo4j的图形化界面进行输入,在数据浏览器中的美元提示符下键入命令进行操控数据库。
1、创建节点
CREATE (dept:Dept { deptno:10,dname:"Accounting",location:"Hyderabad" })
2、查询节点
MATCH (dept: Dept)
RETURN dept.deptno,dept.dname
3、使用现有节点创建关系
MATCH (cust:Customer),(cc:CreditCard)
CREATE (cust)-[r:DO_SHOPPING_WITH{shopdate:"12/12/2014",price:55000}]->(cc)
RETURN r
4、使用新节点创建关系
CREATE (video1:YoutubeVideo1{title:"Action Movie1",updated_by:"Abc",uploaded_date:"10/10/2010"})
-[movie:ACTION_MOVIES{rating:1}]->
(video2:YoutubeVideo2{title:"Action Movie2",updated_by:"Xyz",uploaded_date:"12/12/2012"})
5、查询关系
MATCH (video1:YoutubeVideo1)-[movie:ACTION_MOVIES]->(video2:YoutubeVideo2)
RETURN movie
6、根据条件查询
MATCH (emp:Employee)
WHERE emp.name = 'Abc'
RETURN emp
7、删除节点(只能删除没有关系的节点)
MATCH (e: Employee) DELETE e
8、删除关系(可以连着节点一起删除)
MATCH (cc: CreditCard)-[rel]-(c:Customer)
DELETE cc,c,rel
9、删除节点或关系的属性和标签
MATCH (book { id:122 })
REMOVE book.price
RETURN book
10、修改添加节点或关系属性
MATCH (book:Book)
SET book.title = 'superstar'
RETURN book
11、排序
MATCH (emp:Employee)
RETURN emp.empid,emp.name,emp.salary,emp.deptno
ORDER BY emp.name
12、联合查询(必须两个查询命令属性相同)
MATCH (cc:CreditCard) RETURN cc.id,cc.number
UNION
MATCH (dc:DebitCard) RETURN dc.id,dc.number
13、过滤或限制查询返回的行数
MATCH (emp:Employee)
RETURN emp
LIMIT 2
14、跳过多少行返回数据
MATCH (emp:Employee)
RETURN emp
SKIP 2
15、不存在进行创建,存在不创建
MERGE (gp2:GoogleProfile2{ Id: 201402,Name:"Nokia"})
16、null值查询(新建时不输入任何属性也会出现null值)
MATCH (e:Employee)
WHERE e.id IS NULL
RETURN e.id,e.name,e.sal,e.deptno
17、批量查询in
MATCH (e:Employee)
WHERE e.id IN [123,124]
RETURN e.id,e.name,e.sal,e.deptno
18、字符串函数(大写:UPPER,小写:LOWER,截取:SUBSTRING,替换:REPLACE)
MATCH (e:Employee)
RETURN e.id,UPPER(e.name),e.sal,e.deptno
19、聚合函数(总行数:COUNT,最大值:MAX,最小值:MIN,求和:SUM,平均值:AVG)
MATCH (e:Employee) RETURN COUNT(*)
20、关系函数(关系启点:STARTNODE,关系终点:ENDNODE,关系id:ID,关系类型:TYPE)
MATCH (a)-[movie:ACTION_MOVIES]->(b)
RETURN STARTNODE(movie)
21、创建普通索引
CREATE INDEX ON :Customer (name)
22、创建唯一索引
CREATE CONSTRAINT ON (cc:CreditCard)
ASSERT cc.number IS UNIQUE
23、删除普通索引
DROP INDEX ON :Customer (name)
24、删除唯一索引
DROP CONSTRAINT ON (cc:CreditCard)
ASSERT cc.number IS UNIQUE
25、修改密码
:server change-password
26、case表达式(选择语句)
MATCH(n)
RETURN
CASE n.eyes
WHEN 'blue' THEN 1
WHEN 'brown' THEN 2
ELSE 3
END
AS result
27、深度匹配 (路径长度匹配)
(a)-[*2..4]->(b) // 匹配路径长度为 2 到4 之间 的路径
(a)-[*2..]->(b) // 匹配路径长度大于2的路径
(a)-[*..2]->(b) // 匹配路径长度小于2的路径
(a)-[*]->(b) // 匹配任意长度的路径
match(n) -[r:TYPE*minHops..maxHops]->(m) return r
28、最短路径匹配 shortestPath() 函数
match (martin:Person {name:"name1"}),(oliver:Perspn{name:"name2"}),p = shortestPath((martin)-[*..15]-(oliver))
return p
29、所有最短路径 allShortestPaths()
match (martin:Person {name:"name1"}),(oliver:Perspn{name:"name2"}),p= allShortestPaths((martin)-[*]-(oliver))
return p
导入csv文件
首先从MySQL数据库导出csv文件,复制到import文件夹E:\Program Files (x86)\neo4j-community-3.4.0\import里,然后执行下列语句:
//导入节点 电影类型 == 注意类型转换
LOAD CSV WITH HEADERS FROM "file:///genre.csv" AS line
MERGE (p:Genre{gid:toInteger(line.gid),name:line.gname})
//导入节点 演员信息
LOAD CSV WITH HEADERS FROM 'file:///person.csv' AS line
MERGE (p:Person { pid:toInteger(line.pid),birth:line.birth,
death:line.death,name:line.name,
biography:line.biography,
birthplace:line.birthplace})
// 导入节点 电影信息
LOAD CSV WITH HEADERS FROM "file:///movie.csv" AS line
MERGE (p:Movie{mid:toInteger(line.mid),title:line.title,introduction:line.introduction,
rating:toFloat(line.rating),releasedate:line.releasedate})
// 导入关系 actedin 电影是谁参演的 1对多
LOAD CSV WITH HEADERS FROM "file:///person_to_movie.csv" AS line
match (from:Person{pid:toInteger(line.pid)}),(to:Movie{mid:toInteger(line.mid)})
merge (from)-[r:actedin{pid:toInteger(line.pid),mid:toInteger(line.mid)}]->(to)
//导入关系 电影是什么类型 == 1对多
LOAD CSV WITH HEADERS FROM "file:///movie_to_genre.csv" AS line
match (from:Movie{mid:toInteger(line.mid)}),(to:Genre{gid:toInteger(line.gid)})
merge (from)-[r:is{mid:toInteger(line.mid),gid:toInteger(line.gid)}]->(to)
Neo4j - Java简介
Neo4j提供JAVA API以编程方式执行所有数据库操作。
它支持两种类型的API:
- Neo4j的原生的Java API
- Neo4j Cypher Java API
Neo4j原生Java API是一种低级别的纯JAVA API,用于执行数据库操作。 Neo4j Cypher Java API是简单而强大的JAVA API,用于执行所有CQL命令以执行数据库操作。
Neo4j Java架构
下图显示了Neo4j JAVA API应用程序的体系结构
客户端程序使用Neo4j Java API之一来在Neo4j数据库上交互和执行数据库操作。
Neo4j - 原生Java API
使用idea创建SpringBoot的项目。
1、引入依赖:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.chengkun</groupId>
<artifactId>springboot-neo4j</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot-neo4j</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>8</java.version>
</properties>
<dependencies>
<!-- 集成springboot web组件 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 集成springboot test组件 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- 集成lombok 框架 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<!-- 服务器开发需要的jar包 -->
<groupId>org.neo4j.driver</groupId>
<artifactId>neo4j-java-driver</artifactId>
<version>1.5.0</version>
</dependency>
<dependency>
<!-- 嵌入式开发需要的jar包 -->
<groupId>org.neo4j</groupId>
<artifactId>neo4j</artifactId>
<version>3.5.4</version>
</dependency>
<!-- 文件上传组件 -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>[1.3.3,)</version>
</dependency>
<!--阿里巴巴 fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.56</version>
</dependency>
<!-- 引入Spring封装的jdbc-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!-- 引入mysql数据库连接驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- 引入 Druid 数据源依赖:https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<dependency>
<groupId>org.xmlunit</groupId>
<artifactId>xmlunit-core</artifactId>
</dependency>
<!--swagger2-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
<exclusions>
<exclusion>
<artifactId>guava</artifactId>
<groupId>com.google.guava</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
<!-- google java lib -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>[24.1.1,)</version>
</dependency>
</dependencies>
<profiles>
<profile>
<id>base</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<package.environment>base</package.environment>
</properties>
</profile>
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<package.environment>dev</package.environment>
</properties>
</profile>
<profile>
<id>test</id>
<properties>
<package.environment>test</package.environment>
</properties>
</profile>
</profiles>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
<mainClass>com.chengkun.neo4j.SpringbootNeo4jApplication</mainClass>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>
${project.build.directory}\lib
</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
<encoding>utf8</encoding>
</configuration>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/**</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.yml</include>
<include>**/*.xml</include>
<include>**/*.tld</include>
<include>**/*.doc</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<!--不对excel模板过滤-->
<include>**/*.xlsx</include>
<include>**/*.xls</include>
</includes>
<excludes>
<exclude>**/*.properties</exclude>
<exclude>**/*.yml</exclude>
<exclude>**/*.xml</exclude>
<exclude>**/*.tld</exclude>
<exclude>**/*.doc</exclude>
</excludes>
<filtering>false</filtering>
</resource>
</resources>
</build>
</project>
2、配置文件application.yml
server:
port: 8080
spring:
datasource:
username: root
password: root
url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf-8&autoReconnect=true&useSSL=false&serverTimezone=Asia/Shanghai
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
druid:
initial-size: 5
min-idle: 5
max-active: 20
max-wait: 60000
time-between-eviction-runs-millis: 60000
min-evictable-idle-time-millis: 300000
validation-query: SELECT 1 FROM DUAL
test-while-idle: true
test-on-borrow: false
test-on-return: false
pool-prepared-statements: true
#配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
filters: stat,wall,lombok
max-pool-prepared-statement-per-connection-size: 20
use-global-data-source-stat: true
connection-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
#easypoi配置
main:
allow-bean-definition-overriding: true
#mybatis配置
mybatis:
configuration:
map-underscore-to-camel-case: true
mapper-locations: classpath*:com/chengkun/**/*Mapper.xml
type-aliases-package: com.chengkun.entity
#日志
logging:
config: classpath:logback-spring.xml
#########其他配置##########
##主要用于加载接口程序需要的配置信息到内存中使用 product为加载生产配置 可配置test,product,dev
environment: dev
# 开启swagger
swagger:
enabled: true
# neo4j数据库地址
neo4j:
db_neo4j: D:\neo4j-community-3.5.4-windows\data\databases\graph.db
3、创建节点标签枚举:
package com.chengkun.neo4j.entity;
import org.neo4j.graphdb.Label;
/**
* 自定义节点标签
*
* @author chengkun
* @version v1.0
* @create 2021/3/29 14:59
**/
public enum MyLabel implements Label {
JAVA, SCALA, SQL, NEO4J;
}
4、创建关系类型枚举
package com.chengkun.neo4j.entity;
import org.neo4j.graphdb.RelationshipType;
/**
* 自定义关系类型
*
* @author chengkun
* @version v1.0
* @create 2021/3/29 15:00
**/
public enum MyRelationshipType implements RelationshipType {
JVM_LANGIAGES, NON_JVM_LANGIAGES;
}
5、noe4j参数实体类
package com.chengkun.neo4j.entity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @author chengkun
* @version v1.0
* @create 2021/3/29 19:09
**/
@Data
@ApiModel(description = "neo4j参数实体类")
public class Code {
@ApiModelProperty(value = "id")
private String id;
@ApiModelProperty(value = "节点")
private String node;
@ApiModelProperty(value = "关系")
private String relation;
@ApiModelProperty(value = "属性")
private String property;
@ApiModelProperty(value = "节点标签")
private String label;
@ApiModelProperty(value = "边起点id")
private String nodeFromId;
@ApiModelProperty(value = "边起点标签")
private String nodeFromLabel;
@ApiModelProperty(value = "边终点id")
private String nodeToId;
@ApiModelProperty(value = "边终点标签")
private String nodeToLabel;
@ApiModelProperty(value = "条件语句")
private String where;
@ApiModelProperty(value = "修改语句")
private String update;
@ApiModelProperty(value = "返回结果")
private String result;
}
6、初始化neo4j数据库bean
package com.chengkun.neo4j.config;
import org.neo4j.driver.v1.AuthTokens;
import org.neo4j.driver.v1.Driver;
import org.neo4j.driver.v1.GraphDatabase;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.factory.GraphDatabaseFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.io.File;
/**
* @author chengkun
* @version v1.0
* @create 2021/3/29 15:16
**/
@Configuration
public class Neo4jConfig {
@Value(value = "${neo4j.db_neo4j}")
private String dbNoe4j;
@Value(value = "${neo4j.neo4j_url}")
private String noe4jUrl;
@Value(value = "${neo4j.username}")
private String username;
@Value(value = "${neo4j.password}")
private String password;
//使用内嵌式数据库
@Bean
public GraphDatabaseService getGraphDatabaseService() {
GraphDatabaseFactory dbFactory = new GraphDatabaseFactory();
GraphDatabaseService db = dbFactory.newEmbeddedDatabase(new File(dbNoe4j));
return db;
}
//使用服务器式数据库
@Bean
public Driver getDrive() {
return GraphDatabase.driver(noe4jUrl, AuthTokens.basic(username, password));
}
}
7、创建neo4j操作Controller
package com.chengkun.neo4j.controller;
import com.chengkun.neo4j.entity.Code;
import com.chengkun.neo4j.entity.MyLabel;
import com.chengkun.neo4j.entity.MyRelationshipType;
import io.swagger.annotations.*;
import lombok.extern.log4j.Log4j2;
import org.neo4j.driver.v1.Driver;
import org.neo4j.driver.v1.Record;
import org.neo4j.driver.v1.Session;
import org.neo4j.driver.v1.StatementResult;
import org.neo4j.graphdb.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
import static org.neo4j.driver.v1.Values.parameters;
/**
* @author chengkun
* @version v1.0
* @create 2021/3/29 15:32
**/
@Api(tags = "neo4j增删改查")
@RestController
@Log4j2
@RequestMapping("/neo4j")
public class Neo4jController {
@Autowired
private GraphDatabaseService graphDB; //使用内嵌式数据库
@Autowired
private Driver driver; //使用服务器式数据库(推荐)
@ApiOperation(value = "创建数据(使用内嵌式数据库)")
@GetMapping(value = "/create", produces = "application/text;charset=UTF-8")
public String create() {
Transaction tx = graphDB.beginTx();
try {
Node java = graphDB.createNode(MyLabel.JAVA);
java.setProperty("id", 1);
java.setProperty("name", "java");
Node c = graphDB.createNode(MyLabel.C);
c.setProperty("id", 2);
c.setProperty("name", "c");
Node python = graphDB.createNode(MyLabel.PYTHON);
python.setProperty("id", 3);
python.setProperty("name", "python");
Node scala = graphDB.createNode(MyLabel.SCALA);
scala.setProperty("id", 4);
scala.setProperty("name", "scala");
Node mysql = graphDB.createNode(MyLabel.MYSQL);
mysql.setProperty("id", 5);
mysql.setProperty("name", "mysql");
Node neo4j = graphDB.createNode(MyLabel.NEO4J);
neo4j.setProperty("id", 6);
neo4j.setProperty("name", "neo4j");
Relationship javaMysql = java.createRelationshipTo(mysql, MyRelationshipType.JVM_LANGIAGES);
javaMysql.setProperty("id", 1);
javaMysql.setProperty("name", "java连接mysql");
Relationship cMysql = c.createRelationshipTo(mysql, MyRelationshipType.NON_JVM_LANGIAGES);
cMysql.setProperty("id", 2);
cMysql.setProperty("name", "c连接mysql");
Relationship pythonMysql = python.createRelationshipTo(mysql, MyRelationshipType.NON_JVM_LANGIAGES);
pythonMysql.setProperty("id", 3);
pythonMysql.setProperty("name", "python连接mysql");
Relationship javaNeo4j = java.createRelationshipTo(neo4j, MyRelationshipType.JVM_LANGIAGES);
javaNeo4j.setProperty("id", 4);
javaNeo4j.setProperty("name", "java连接neo4j");
Relationship scalaNeo4j = scala.createRelationshipTo(neo4j, MyRelationshipType.NON_JVM_LANGIAGES);
scalaNeo4j.setProperty("id", 5);
scalaNeo4j.setProperty("name", "scala连接neo4j");
tx.success();
} finally {
tx.close();
}
return "创建成功";
}
@ApiOperation(value = "根据id查询节点(使用内嵌式数据库)")
@GetMapping(value = "/getNode", produces = "application/text;charset=UTF-8")
public String getNode(@RequestParam("id") Integer id) {
Transaction tx = graphDB.beginTx();
Node node;
try {
node = graphDB.findNode(MyLabel.JAVA, "id", id); //这里类型必须与保存的类型一致
System.out.println(node.getId());
System.out.println(node.getLabels());
System.out.println(node.getAllProperties());
tx.success();
} finally {
tx.close();
}
return "查询成功";
}
@ApiOperation(value = "查看所有(使用内嵌式数据库)")
@GetMapping(value = "/findAll", produces = "application/text;charset=UTF-8")
public String findAll() {
Transaction tx = graphDB.beginTx();
try {
for (Node node : graphDB.getAllNodes()) {
System.out.println(node.getId());
System.out.println(node.getLabels());
System.out.println(node.getAllProperties());
for (Relationship relationship : node.getRelationships()) {
System.out.println(relationship.getId());
System.out.println(relationship.getType());
System.out.println(relationship.getAllProperties());
}
}
tx.success();
} finally {
tx.close();
}
return "查询成功";
}
@ApiOperation(value = "删除节点以及关联的边(使用内嵌式数据库)")
@GetMapping(value = "/deleteNode", produces = "application/text;charset=UTF-8")
public String deleteNode(@RequestParam("id") Integer id) {
Transaction tx = graphDB.beginTx();
try {
Node scala = graphDB.findNode(MyLabel.SCALA, "id", id);
Iterable<Relationship> relationships = scala.getRelationships(MyRelationshipType.NON_JVM_LANGIAGES);
//删除边
for (Relationship relationship : relationships) {
relationship.delete();
}
//删除节点
scala.delete();
System.out.println("delete ok");
tx.success();
} finally {
tx.close();
}
return "删除成功";
}
@ApiOperation(value = "修改节点以及关联的边(使用内嵌式数据库)")
@GetMapping(value = "/updateNode", produces = "application/text;charset=UTF-8")
public String updateNode(@RequestParam("id") Integer id) {
Transaction tx = graphDB.beginTx();
try {
Node c = graphDB.findNode(MyLabel.C, "id", id);
Iterable<Relationship> relationships = c.getRelationships(Direction.OUTGOING, MyRelationshipType.NON_JVM_LANGIAGES);
//修改边
for (Relationship relationship : relationships) {
relationship.setProperty("type", "c->out->other");
}
//修改节点
c.setProperty("type", "c语言");
System.out.println("update ok");
tx.success();
} finally {
tx.close();
}
return "修改成功";
}
@ApiOperation(value = "删除所有(使用内嵌式数据库)")
@GetMapping(value = "/deleteAll", produces = "application/text;charset=UTF-8")
public String deleteAll() {
Transaction tx = graphDB.beginTx();
try {
for (Node node : graphDB.getAllNodes()) {
for (Relationship relationship : node.getRelationships()) {
relationship.delete();
}
node.delete();
}
tx.success();
} finally {
tx.close();
}
return "删除所有";
}
@ApiOperation(value = "创建数据(使用服务器式数据库)")
@GetMapping(value = "create1", produces = "application/text;charset=UTF-8")
public String create1() {
try {
Session session = driver.session();
session.run("CREATE (a:Person {id: {id}, name: {name}, title: {title}})",
parameters("id", 1, "name", "Arthur001", "title", "King001"));
StatementResult result = session.run("MATCH (a:Person) WHERE a.name = {name} RETURN a.id as id,a.name AS name, a.title AS title",
parameters("name", "Arthur001"));
while (result.hasNext()) {
Record record = result.next();
System.out.println(record.get("id").asInt() + " " + record.get("title").asString() + " " + record.get("name").asString());
}
session.close();
System.out.println("使用服务器式数据库创建数据成功");
} catch (Exception e) {
log.info("使用服务器式数据库创建数据失败");
return "使用服务器式数据库创建数据失败";
}
return "使用服务器式数据库创建数据成功";
}
@ApiOperation(value = "修改数据(使用服务器式数据库)")
@ApiImplicitParams({
@ApiImplicitParam(name = "id", value = "修改节点id"),
@ApiImplicitParam(name = "name", value = "修改后的名称"),
})
@GetMapping(value = "update", produces = "application/json;charset=UTF-8")
public void update(@RequestParam("id") Integer id, @RequestParam("name") String name) {
try {
Session session = driver.session();
StatementResult result = session.run("MATCH (a:Person) WHERE a.id={id} SET a.name = {name} RETURN a.id as id,a.name AS name, a.title AS title",
parameters("id", id, "name", name));
while (result.hasNext()) {
Record record = result.next();
System.out.println(record.get("id").asInt() + " " + record.get("title").asString() + " " + record.get("name").asString());
}
session.close();
System.out.println("使用服务器式数据库修改数据成功");
} catch (Exception e) {
log.info("使用服务器式数据库修改数据失败");
}
}
@ApiOperation(value = "添加关系(使用服务器式数据库)")
@PostMapping(value = "relate", produces = "application/json;charset=UTF-8")
public void relate(@RequestBody Code code) {
try {
Session session = driver.session();
session.run("MATCH (a:" + code.getNodeFromLabel() + "), (b:" + code.getNodeToLabel() + ") " +
"WHERE a.id = " + code.getNodeFromId() + " AND b.id = " + code.getNodeToId()
+ " CREATE (a)-[:" + code.getRelation() + "]->(b)");
session.close();
System.out.println("使用服务器式数据库添加边成功");
} catch (Exception e) {
log.info("使用服务器式数据库添加边失败");
}
}
@ApiOperation(value = "删除数据(使用服务器式数据库)")
@GetMapping(value = "delete", produces = "application/text;charset=UTF-8")
public String delete(@RequestParam("id") Integer id) {
try {
Session session = driver.session();
session.run("match (n:Person) where n.id = {id} delete n",
parameters("id", id));
session.close();
System.out.println("使用服务器式数据库删除数据成功");
} catch (Exception e) {
log.info("使用服务器式数据库删除数据失败");
return "使用服务器式数据库删除数据失败";
}
return "使用服务器式数据库删除数据成功";
}
@ApiOperation(value = "删除关系(使用服务器式数据库)")
@PostMapping(value = "deleteRelate", produces = "application/json;charset=UTF-8")
public void deleteRelate(@RequestBody Code code) {
try {
Session session = driver.session();
//不知道为什么执行报错
// session.run("MATCH (a:{NodeFromLabel})-[r:{relation}]->(b:{nodeToLabel}) WHERE a.id={nodeFromId} and b.id={nodeToId} DELETE r",
// parameters("NodeFromLabel", code.getNodeFromLabel(), "relation", code.getRelation(), "nodeToLabel", code.getNodeToLabel(), "nodeFromId", code.getNodeFromId(), "nodeToId", code.getNodeToId()));
session.run("MATCH (a:" + code.getNodeFromLabel() + ")-[r:" + code.getRelation() + "]->(b:" + code.getNodeToLabel() + ") WHERE a.id = " + code.getNodeFromId() + " and b.id = " + code.getNodeToId() + " DELETE r");
session.close();
System.out.println("使用服务器式数据库删除数据成功");
} catch (Exception e) {
log.info("使用服务器式数据库删除数据失败");
}
}
@ApiOperation(value = "查询数据(使用服务器式数据库)")
@GetMapping(value = "search", produces = "application/json;charset=UTF-8")
public List<String> search() {
List<String> resultList = new ArrayList<>();
try {
Session session = driver.session();
StatementResult result = session.run("match (n) return n.id as id,n.name as name");
while (result.hasNext()) {
Record record = result.next();
resultList.add(record.get("id").toString() + " " + record.get("name").toString());
}
session.close();
System.out.println("使用服务器式数据库查询数据成功");
} catch (Exception e) {
log.info("使用服务器式数据库查询数据失败");
}
return resultList;
}
}
注意:
1、使用内嵌式数据库,neo4j界面启动时会锁住整个数据库,这时候java就无法连接这个据库
2、使用服务器形式数据库,可以跟界面进行联调,它比嵌入式配置更安全,推荐使用这种
Neo4j与Spring数据
Spring DATA Neo4J - 架构
下图显示了Spring DATA Neo4j模块的体系结构
Spring DATA Neo4j存储库
它提供了不同的API来支持不同的场景
- Neo4jRepository
- CrudRepository
- PaginationAndSortingRepository
这些是Java类。 每个具有执行Neo4j数据库操作的特定目的,继承关系是:Neo4jRepository->PaginationAndSortingRepository->CrudRepository
S.No. | Spring 数据 Neo4j 类 | 用法 |
---|---|---|
1 | Neo4jRepository | 它用于执行Basic Neo4j DB操作。 |
2 | CrudRepository | 它用于使用Cypher查询语言(CQL)执行Neo4j CRUD操作。 |
3 | PaginationAndSortingRepository | 它用于执行Neo4j CQL查询结果的分页和排序。。 |
Spring Data Neo4j - API
1、添加Spring Data Neo4j相关依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-neo4j</artifactId>
</dependency>
2、application.yml添加Neo4j环境配置
spring:
neo4j:
uri: bolt://localhost:7687
authentication:
username: neo4j
password: neo4j
3、Neo4j中要定义节点,使用Spring Data Neo4j的注解@NodeEntity,标记该类为节点,节点名称为 Student
package com.chengkun.neo4j.entity;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.*;
import org.neo4j.ogm.annotation.*;
import java.util.ArrayList;
import java.util.List;
/**
* @author chengkun
* @version v1.0
* @create 2021/3/30 21:46
**/
@Data
@NodeEntity("Student")
public class Student{
/**
* neo4j 生成的id
*/
@Id
@GeneratedValue
private Long id;
/**
* 属性,name
*/
@Property("name")
private String name;
/**
* 属性,age
*/
@Property("age")
private Integer age;
/**
* 关系,定义为友谊 指向别人
*/
@JsonIgnore // 禁止json序列化无限遍历
@Relationship(type = "FRIENDSHIP_RELATION", direction = Relationship.OUTGOING)
private List<FriendshipRelation> friendshipRelationOutList;
/**
* 关系,定义为友谊 指向自己
*/
@JsonIgnore
@Relationship(type = "FRIENDSHIP_RELATION", direction = Relationship.INCOMING)
private List<FriendshipRelation> friendshipRelationInList;
/**
* 添加友谊的关系
*
* @param friendshipRelation
*/
public void addOutRelation(FriendshipRelation friendshipRelation) {
if (this.friendshipRelationOutList == null) {
this.friendshipRelationOutList = new ArrayList<>();
}
this.friendshipRelationOutList.add(friendshipRelation);
}
/**
* 添加友谊的关系
*
* @param friendshipRelation
*/
public void addInRelation(FriendshipRelation friendshipRelation) {
if (this.friendshipRelationInList == null) {
this.friendshipRelationInList = new ArrayList<>();
}
this.friendshipRelationInList.add(friendshipRelation);
}
}
4、Neo4j也要定义关系,使用Spring Data Neo4j的注解@RelationshipEntity,标记其为关系,关系名为 FRIENDSHIP_RELATION,在里面定义StartNode和EndNode
package com.chengkun.neo4j.entity;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Getter;
import lombok.Setter;
import org.neo4j.ogm.annotation.*;
/**
* 关系不能有toString方法
*
* @author chengkun
* @version v1.0
* @create 2021/3/30 22:01
**/
@Getter
@Setter
@RelationshipEntity(type = "FRIENDSHIP_RELATION")
public class FriendshipRelation {
@Id
@GeneratedValue
private Long id;
@Property("name")
private String name;
@StartNode
private Student from;
@EndNode
private Student to;
}
注意:
JSON序列化注意事项:这里的关系里面有节点,节点里面有关系,造成循环依赖,在序列化中会造成栈溢出,就需要使用@JsonIgnoreProperties或@JsonIgnore进行序列化属性忽略
- @JsonIgnore:添加到字段上是直接忽略该字段,序列化后就没有该字段,如,在Student的两个关系字段上表示不进行序列化关系字段
/**
* 关系,定义为友谊 指向别人
*/
@JsonIgnore // 禁止json序列化无限遍历
@Relationship(type = "FRIENDSHIP_RELATION", direction = Relationship.OUTGOING)
private List<FriendshipRelation> friendshipRelationOutList;
/**
* 关系,定义为友谊 指向自己
*/
@JsonIgnore
@Relationship(type = "FRIENDSHIP_RELATION", direction = Relationship.INCOMING)
private List<FriendshipRelation> friendshipRelationInList;
- @JsonIgnoreProperties:添加在字段上,并标注不进行序列化的字段,如,在Student的两个关系字段上,并添加忽略序列化的属性,该字段上是FriendshipRelation,所以应该表示FriendshipRelation类不需要序列化的属性,@JsonIgnoreProperties({“from”,
“to”})
/**
* 关系,定义为友谊 指向别人
*/
@JsonIgnoreProperties({"from", "to"}) // 禁止json序列化无限遍历
@Relationship(type = "FRIENDSHIP_RELATION", direction = Relationship.OUTGOING)
private List<FriendshipRelation> friendshipRelationOutList;
/**
* 关系,定义为友谊 指向自己
*/
@JsonIgnoreProperties({"from", "to"})
@Relationship(type = "FRIENDSHIP_RELATION", direction = Relationship.INCOMING)
private List<FriendshipRelation> friendshipRelationInList;
5、StudentRepository为数据库操作,因为后面有删除关系,所以需要@Transactional
package com.chengkun.neo4j.repository;
import com.chengkun.neo4j.entity.FriendshipRelation;
import com.chengkun.neo4j.entity.Student;
import org.springframework.data.neo4j.annotation.Query;
import org.springframework.data.neo4j.repository.Neo4jRepository;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/**
* @author chengkun
* @version v1.0
* @create 2021/3/31 9:30
**/
@Transactional
@Repository
public interface StudentRepository extends Neo4jRepository<Student, Long> {
/**
* 通过name查找学生node
*
* @param name
* @return
*/
Student findByName(String name);
/**
* 根据name获取学生 out 友谊关系
*
* @param name
* @return
*/
@Query("match p=(a:Student)-[r:FRIENDSHIP_RELATION]->(b:Student) where a.name = {0} return p")
List<FriendshipRelation> outFriendship(String name);
/**
* 根据name获取学生 in 友谊关系
*
* @param name
* @return
*/
@Query("match p=(a:Student)<-[r:FRIENDSHIP_RELATION]-(b:Student) where a.name={0} return p")
List<FriendshipRelation> inFriendship(String name);
/**
* 根据name获取学生 both 友谊关系
*
* @param name
* @return
*/
@Query("match p=(a:Student) <- [r:FRIENDSHIP_RELATION] ->(b:Student) <- [rr:FRIENDSHIP_RELATION] -> (c:Student) where b.name = {0} return p")
List<FriendshipRelation> bothFriendship(String name);
}
6、创建SpringDataDeo4jController进行测试
package com.chengkun.neo4j.controller;
import com.chengkun.neo4j.entity.FriendshipRelation;
import com.chengkun.neo4j.entity.Student;
import com.chengkun.neo4j.repository.StudentRepository;
import com.google.common.collect.Lists;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* @author chengkun
* @version v1.0
* @create 2021/3/31 10:21
**/
@Api(tags = "spring-data-neo4j增删改查")
@RestController
@Log4j2
@RequestMapping("/spring-data-neo4j")
public class SpringDataDeo4jController {
@Autowired
private StudentRepository studentRepository;
@ApiOperation(value = " 保存单个节点(使用spring-data-neo4j)")
@PostMapping(value = "/saveStudentNode", produces = "application/text;charset=UTF-8")
public String saveStudentNode(String name, int age) {
Student student = new Student();
student.setName(name);
student.setAge(age);
studentRepository.save(student);
return "创建成功";
}
@ApiOperation(value = "保存批量节点(使用spring-data-neo4j)")
@GetMapping(value = "saveAllStudentNode", produces = "application/text;charset=UTF-8")
public String saveAllStudentNode() {
Student student1 = new Student();
student1.setName("张三");
student1.setAge(18);
Student student2 = new Student();
student2.setName("李四");
student2.setAge(19);
Student student3 = new Student();
student3.setName("王五");
student3.setAge(18);
Student student4 = new Student();
student4.setName("赵六");
student4.setAge(20);
List<Student> list = Lists.newArrayList(student1, student2, student3, student4);
studentRepository.saveAll(list);
return "创建成功";
}
@ApiOperation(value = "根据name查询学生(使用spring-data-neo4j)")
@PostMapping(value = "/findStudentByName", produces = "application/json;charset=UTF-8")
@ApiImplicitParam(name = "name", value = "学生名称")
public Student findStudentByName(@RequestParam("name") String name) {
Student student = studentRepository.findByName(name);
return student;
}
@ApiOperation(value = "修改学生名称(使用spring-data-neo4j)")
@GetMapping(value = "/updateStudentByName", produces = "application/json;charset=UTF-8")
@ApiImplicitParams({
@ApiImplicitParam(name = "name", value = "修改前学生名称"),
@ApiImplicitParam(name = "updateName", value = "修改后学生名称"),
})
public Student updateStudentByName(String name, String updateName) {
Student student = studentRepository.findByName(name);
student.setName(updateName);
studentRepository.save(student);
return student;
}
@ApiOperation(value = "根据名称删除学生(使用spring-data-neo4j)")
@GetMapping(value = "/deleteStudentByName", produces = "application/json;charset=UTF-8")
@ApiImplicitParams({
@ApiImplicitParam(name = "name", value = "修改前学生名称"),
})
public Student deleteStudentByName(String name) {
Student student = studentRepository.findByName(name);
studentRepository.delete(student);
return student;
}
@ApiOperation(value = "删除所有学生(使用spring-data-neo4j)")
@GetMapping(value = "/deleteAllStudent", produces = "application/text;charset=UTF-8")
public String deleteAllStudent() {
studentRepository.deleteAll();
return "删除成功";
}
@ApiOperation(value = "查询全部(使用spring-data-neo4j)")
@GetMapping(value = "/findAll", produces = "application/json;charset=UTF-8")
public List<Student> findAll() {
List<Student> studentNodeList = Lists.newArrayList(studentRepository.findAll());
return studentNodeList;
}
/**
* 分页查询
*/
@ApiOperation(value = "分页查询(使用spring-data-neo4j)")
@GetMapping(value = "/pageFindAll", produces = "application/json;charset=UTF-8")
@ApiImplicitParams({
@ApiImplicitParam(name = "page", value = "第几页"),
@ApiImplicitParam(name = "size", value = "每页条数"),
})
public Page<Student> pageFindAll(int page, int size) {
// page从0开始
Pageable pageable = PageRequest.of(page - 1, size);
Page<Student> studentNodePage = studentRepository.findAll(pageable);
return studentNodePage;
}
@ApiOperation(value = "保存友谊关系(使用spring-data-neo4j)")
@GetMapping(value = "/saveFriendShip", produces = "application/text;charset=UTF-8")
@ApiImplicitParams({
@ApiImplicitParam(name = "studentFromName", value = "关系起点名称"),
@ApiImplicitParam(name = "studentToName", value = "关系终点名称"),
})
public String saveFriendShip(String studentFromName, String studentToName) {
Student studentFrom = studentRepository.findByName(studentFromName);
Student studentTo = studentRepository.findByName(studentToName);
FriendshipRelation studentFromToRelation = new FriendshipRelation();
studentFromToRelation.setName("友谊关系");
// 添加from
studentFromToRelation.setFrom(studentFrom);
//添加to
studentFromToRelation.setTo(studentTo);
//只需要在from节点保存关系即可
studentFrom.addOutRelation(studentFromToRelation);
studentRepository.save(studentFrom);
return "保存成功";
}
@ApiOperation(value = "保存双向友谊关系(使用spring-data-neo4j)")
@GetMapping(value = "/saveBrotherFriendShip", produces = "application/text;charset=UTF-8")
@ApiImplicitParams({
@ApiImplicitParam(name = "name1", value = "学生名称1"),
@ApiImplicitParam(name = "name2", value = "学生名称2"),
})
public String saveBrotherFriendShip(String name1, String name2) {
Student studentFrom = studentRepository.findByName(name1);
Student studentTo = studentRepository.findByName(name2);
FriendshipRelation studentFromToRelation = new FriendshipRelation();
studentFromToRelation.setName("友谊关系");
// 添加from
studentFromToRelation.setFrom(studentTo);
//添加to
studentFromToRelation.setTo(studentTo);
//from->to
studentFrom.addOutRelation(studentFromToRelation);
FriendshipRelation studentToFromRelation = new FriendshipRelation();
studentToFromRelation.setName("友谊关系");
// 添加from
studentToFromRelation.setFrom(studentTo);
//添加to
studentToFromRelation.setTo(studentFrom);
//to->from
studentFrom.addInRelation(studentToFromRelation);
studentRepository.save(studentFrom);
return "保存成功";
}
@ApiOperation(value = "根据名称查询in关系(使用spring-data-neo4j)")
@GetMapping(value = "/inFriendshipByName", produces = "application/json;charset=UTF-8")
@ApiImplicitParams({
@ApiImplicitParam(name = "name", value = "学生名称"),
})
public List<FriendshipRelation> inFriendshipByName(@RequestParam("name") String name) {
List<FriendshipRelation> friendshipRelations = studentRepository.inFriendship(name);
return friendshipRelations;
}
@ApiOperation(value = "根据名称查询out关系(使用spring-data-neo4j)")
@GetMapping(value = "/outFriendshipByName", produces = "application/json;charset=UTF-8")
@ApiImplicitParams({
@ApiImplicitParam(name = "name", value = "学生名称"),
})
public List<FriendshipRelation> outFriendshipByName(String name) {
List<FriendshipRelation> friendshipRelations = studentRepository.outFriendship(name);
return friendshipRelations;
}
@ApiOperation(value = "获取兄弟关系(使用spring-data-neo4j)")
@GetMapping(value = "/getBrotherFriendShip", produces = "application/json;charset=UTF-8")
@ApiImplicitParams({
@ApiImplicitParam(name = "name", value = "学生名称"),
})
public List<FriendshipRelation> getBrotherFriendShip(String name) {
List<FriendshipRelation> friendshipRelations = studentRepository.bothFriendship(name);
return friendshipRelations;
}
}
总结:
- java连接嵌入式数据库,因为是内嵌的,在操作数据库时无法查询数据界面,不太方便,操作使用有点类似jpa。
- java连接服务式数据库,需要使用驱动进行连接,完全使用cql语句进行操作,需要打开neo4j的bolt连接端口7687,操作有点类似mybatis。
- 使用Spring Data Neo4j连接数据库,支持cql和内置方法,相当于上面两种混合型,需要注意版本问题,这个是Spring Boot的老问题,每个版本差距还是很大的。
源码地址:springboot-neo4j
参考网址:
Neo4j安装及简单使用
W3Cschool-neo4j教程
Neo4j的使用与Java调用实例
Spring Data Neo4j 使用
Sping Data Neo4j官网