Spring Boot 整合 SpringDataNeo4j 并封装工具类解析PathValue
GitHub:
link. 欢迎star
注意:本篇博客风格(不多比比就是撸代码!!!)
一、Neo4j
百度百科:Neo4j是一个高性能的,NOSQL图形数据库,它将结构化数据存储在网络上而不是表中。它是一个嵌入式的、基于磁盘的、具备完全的事务特性的Java持久化引擎,但是它将结构化数据存储在网络(从数学角度叫做图)上而不是表中。Neo4j也可以被看作是一个高性能的图引擎,该引擎具有成熟数据库的所有特性。程序员工作在一个面向对象的、灵活的网络结构下而不是严格、静态的表中——但是他们可以享受到具备完全的事务特性、企业级的数据库的所有好处。
二、Neo4j客户端浏览器

三、maven依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-neo4j</artifactId>
</dependency>
四、节点/关系映射
1.NodePerson.java
import lombok.Builder;
import lombok.Data;
import org.springframework.data.neo4j.core.schema.*;
import java.io.Serializable;
@Builder
@Data
@Node("person")
public class NodePerson implements Serializable {
@Id
@GeneratedValue
private Long id;
@Property("name")
private String name;
@Relationship(type = "location", direction = Relationship.Direction.OUTGOING)
private NodeLocation location;
@Relationship(type = "friend", direction = Relationship.Direction.OUTGOING)
private RelationFriend friend;
}
2.NodeLocation.java
import lombok.Builder;
import lombok.Data;
import org.springframework.data.neo4j.core.schema.GeneratedValue;
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 java.io.Serializable;
@Builder
@Data
@Node("location")
public class NodeLocation implements Serializable {
@Id
@GeneratedValue
private Long id;
@Property("name")
private String name;
}
3.RelationFriend.java
import lombok.Builder;
import lombok.Data;
import org.springframework.data.neo4j.core.schema.GeneratedValue;
import org.springframework.data.neo4j.core.schema.Id;
import org.springframework.data.neo4j.core.schema.RelationshipProperties;
import org.springframework.data.neo4j.core.schema.TargetNode;
import java.io.Serializable;
import java.util.List;
@Builder
@Data
@RelationshipProperties
public class RelationFriend implements Serializable {
@Id
@GeneratedValue
private Long id;
@TargetNode
private List<NodePerson> personList;
private String value;
}
四.dao层操作图数据库
1.NodePersonRepository.java
import com.andon.springbootneo4j.model.NodePerson;
import org.springframework.data.neo4j.repository.Neo4jRepository;
import org.springframework.data.neo4j.repository.query.Query;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface NodePersonRepository extends Neo4jRepository<NodePerson, Long> {
@Query(value = "MATCH (n:person) WHERE n.name=$name RETURN n")
List<NodePerson> matchPersonWhereName(String name);
}
2.NodeLocationRepository.java
import com.andon.springbootneo4j.model.NodeLocation;
import org.springframework.data.neo4j.repository.Neo4jRepository;
import org.springframework.data.neo4j.repository.query.Query;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface NodeLocationRepository extends Neo4jRepository<NodeLocation, Long> {
@Query(value = "MATCH (n:location) WHERE n.name=$name RETURN n")
List<NodeLocation> matchLocationWhereName(String name);
}
3.RelationFriendRepository.java
import com.andon.springbootneo4j.model.RelationFriend;
import org.springframework.data.neo4j.repository.Neo4jRepository;
import org.springframework.data.neo4j.repository.query.Query;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface RelationFriendRepository extends Neo4jRepository<RelationFriend, Long> {
@Query(value = "MATCH relation=(p1:person)-[r:friend]->(p2:person) WHERE r.value=$value RETURN relation")
List<Object> matchFriendWhereValue(String value);
@Query(value = "MATCH data=(p)-[*1..3]-(p2) WHERE p.name='关羽' RETURN data")
List<Object> test();
}
五、Neo4jUtil.java 解析节点/关系参数
import org.neo4j.driver.internal.value.PathValue;
import org.neo4j.driver.types.Node;
import org.neo4j.driver.types.Path;
import org.neo4j.driver.types.Relationship;
import org.springframework.util.ObjectUtils;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@SuppressWarnings("DuplicatedCode")
public class Neo4jUtil {
public static <T> List<Map<String, Object>> getNodeList(List<Object> pathValueList, Class<T> tClass) {
List<Map<String, Object>> mapList = new ArrayList<>();
Map<String, List<Map<String, Object>>> listMap = new HashMap<>();
Map<String, List<String>> idListMap = new HashMap<>();
List<String> nameFieldList = new ArrayList<>();
for (Field declaredField : tClass.getDeclaredFields()) {
nameFieldList.add(declaredField.getName());
}
pathValueList.forEach((o) -> {
PathValue pathValue = (PathValue) o;
Path segments = pathValue.asPath();
Iterable<Node> nodes = segments.nodes();
nodes.forEach((node) -> {
List<String> labelList = new ArrayList<>();
Iterable<String> labels = node.labels();
labels.forEach(labelList::add);
String nodeLabel = String.join(",", labelList);
List<Map<String, Object>> maps = listMap.get(nodeLabel);
if (ObjectUtils.isEmpty(maps))
maps = new ArrayList<>();
List<String> idList = idListMap.get(nodeLabel);
if (ObjectUtils.isEmpty(idList))
idList = new ArrayList<>();
String id = String.valueOf(node.id());
if (!idList.contains(id)) {
Map<String, Object> map = new HashMap<>();
map.put("nodeId", node.id());
nameFieldList.forEach((nameField) -> {
if (node.containsKey(nameField))
map.put(nameField, node.get(nameField).asObject());
});
map.put("nodeLabel", nodeLabel);
maps.add(map);
idList.add(id);
}
listMap.put(nodeLabel, maps);
idListMap.put(nodeLabel, idList);
});
});
listMap.forEach((key, value) -> {
Map<String, Object> map = new HashMap<>();
map.put("nodeLabel", key);
map.put("nodeList", value);
mapList.add(map);
});
return mapList;
}
public static <T> List<Map<String, Object>> getRelationList(List<Object> pathValueList, Class<T> tClass) {
List<Map<String, Object>> mapList = new ArrayList<>();
Map<String, List<Map<String, Object>>> listMap = new HashMap<>();
Map<String, List<String>> idListMap = new HashMap<>();
List<String> nameFieldList = new ArrayList<>();
for (Field declaredField : tClass.getDeclaredFields()) {
nameFieldList.add(declaredField.getName());
}
pathValueList.forEach((o) -> {
PathValue pathValue = (PathValue) o;
Path segments = pathValue.asPath();
Iterable<Relationship> relationships = segments.relationships();
relationships.forEach((relationship) -> {
String relationshipType = relationship.type();
List<Map<String, Object>> maps = listMap.get(relationshipType);
if (ObjectUtils.isEmpty(maps))
maps = new ArrayList<>();
List<String> idList = idListMap.get(relationshipType);
if (ObjectUtils.isEmpty(idList))
idList = new ArrayList<>();
String id = String.valueOf(relationship.id());
if (!idList.contains(id)) {
Map<String, Object> map = new HashMap<>();
map.put("relationshipId", relationship.id());
map.put("relationshipType", relationship.type());
map.put("startNodeId", relationship.startNodeId());
map.put("endNodeId", relationship.endNodeId());
nameFieldList.forEach((nameField) -> {
if (relationship.containsKey(nameField))
map.put(nameField, relationship.get(nameField).asObject());
});
maps.add(map);
idList.add(id);
}
listMap.put(relationshipType, maps);
idListMap.put(relationshipType, idList);
});
});
listMap.forEach((key, value) -> {
Map<String, Object> map = new HashMap<>();
map.put("relationshipType", key);
map.put("relationshipList", value);
mapList.add(map);
});
return mapList;
}
}
七、application.yml
server:
port: 8888
spring:
neo4j:
uri: bolt://####:7687
authentication:
username: ####
password: ####
八、测试

GitHub: link. 欢迎star
|