在上一章中因为spring-data-Neo4j最新版本中一些api问题,导致生成的关系会变成节点,使用了另一种方式生成关系,但是那种方式无法正常生成关系的属性,这一篇文章将不使用官方提供的增删查改api,使用记录一下使用字符串拼接的方式来实现节点,关系的插入,下面记录一下实现工具类
不用spring-data0Neo4j的api来实现对节点的增删改查原因
- 因为api中继承Neo4jRepository的方法来实现,新增时,需要指定实体类,以及指定关系,无法做到动态传参;
- 就是因为上一章中使用官方给出的demo无法正常插入节点和关系
插入节点(插入单个属性)
import jakarta.annotation.Resource;
import org.neo4j.driver.Driver;
import org.neo4j.driver.Session;
import org.neo4j.driver.Value;
import org.neo4j.driver.Values;
import org.springframework.stereotype.Component;
import java.util.Map;
@Component
public class Neo4jUtil {
@Resource
private Driver driver;
/**
* 功能描述:创建节点
*
* @param label 节点名
* @param propertyName 属性名称
* @param propertyValue 属性值
* @author zhongzy
* @date 2024/05/16
*/
public void createNode(String label, String propertyName, String propertyValue){
try(Session session = driver.session()){
session.run("CREATE (n:" + label + " {" + propertyName + ": $propertyValue})", parameters("propertyValue", propertyValue));
}
}
private static Value parameters(Object... values) {
return Values.parameters(values);
}
}
插入节点(插入多个属性)
/**
* 功能描述:创建节点多个属性值
*
* @param label 标签
* @param properties 多属性
* @author zhongzy
* @date 2024/05/16
*/
public void createNode(String label, Map<String, Object> properties){
try(Session session = driver.session()){
StringBuilder sb = new StringBuilder("CREATE (n:" + label + " {");
for(Map.Entry<String, Object> entry : properties.entrySet()){
sb.append(entry.getKey()).append(": $").append(entry.getKey()).append(", ");
}
sb.setLength(sb.length() - 2);
sb.append("})");
session.run(sb.toString(), Values.value(properties));
}
}
指定节点添加关系(初级版本)
/**
* 功能描述:
*
* @param fromLabel 起始节点
* @param fromProperty 起始属性
* @param fromPropertyValue 起始属性值
* @param toLabel 目标节点
* @param toProperty 目标属性
* @param toPropertyValue 目标属性值
* @param relationshipType 关系类型
* @author zhongzy
* @date 2024/05/16
*/
public void createRelationship(String fromLabel, String fromProperty, String fromPropertyValue,
String toLabel, String toProperty, String toPropertyValue, String relationshipType){
try(Session session = driver.session()){
session.run("MATCH (a:" + fromLabel + " {" + fromProperty + ": $fromPropertyValue}) "
+ "MATCH (b:" + toLabel + " {" + toProperty + ": $toPropertyValue}) "
+ "CREATE (a)-[r:" + relationshipType + "]->(b)",
parameters("fromPropertyValue", fromPropertyValue, "toPropertyValue", toPropertyValue));
}
}
指定节点添加关系以及关系属性
因为上面这个方法会有问题,节点属性不一定传入,所以拼接会有问题,进行一下修改
/**
* 功能描述:
*
* @param fromLabel 起始节点
* @param fromProperties 起始节点属性
* @param toLabel 目标节点
* @param toProperties 目标节点属性
* @param relationshipType 关系类型
* @param relationshipProperties 关系属性
* @author zhongzy
* @date 2024/05/16
*/
public void createRelationship(String fromLabel, Map<String, Object> fromProperties,
String toLabel, Map<String, Object> toProperties,
String relationshipType, Map<String, Object> relationshipProperties) {
try (Session session = driver.session()) {
StringBuilder sb = new StringBuilder("MATCH (a:" + fromLabel);
appendProperties(sb, "a", fromProperties);
sb.append(") MATCH (b:" + toLabel);
appendProperties(sb, "b", toProperties);
sb.append(") CREATE (a)-[r:" + relationshipType);
appendProperties(sb, "r", relationshipProperties);
sb.append("]->(b)");
Map<String, Object> parameters = new HashMap<>();
addPropertiesToParameters(parameters, addPrefixToProperties(fromProperties, "a_"));
addPropertiesToParameters(parameters, addPrefixToProperties(toProperties, "b_"));
addPropertiesToParameters(parameters, addPrefixToProperties(relationshipProperties, "r_"));
session.run(sb.toString(), parameters);
}
}
private void appendProperties(StringBuilder sb, String variable, Map<String, Object> properties) {
if (properties != null && !properties.isEmpty()) {
sb.append(" {");
for (Map.Entry<String, Object> entry : properties.entrySet()) {
sb.append(entry.getKey()).append(": $").append(variable).append("_").append(entry.getKey()).append(", ");
}
sb.setLength(sb.length() - 2);
sb.append("}");
}
}
/**
* 功能描述:这里占位符需要单独的标识来拼接
*
* @param properties 属性
* @param prefix 前缀
* @return {@link Map }<{@link String }, {@link Object }>
* @author zhongzy
* @date 2024/05/16
*/
private Map<String, Object> addPrefixToProperties(Map<String, Object> properties, String prefix) {
Map<String, Object> prefixedProperties = new HashMap<>();
for (Map.Entry<String, Object> entry : properties.entrySet()) {
String prefixedKey = prefix + entry.getKey();
prefixedProperties.put(prefixedKey, entry.getValue());
}
return prefixedProperties;
}
private void addPropertiesToParameters(Map<String, Object> parameters, Map<String, Object> properties) {
if (properties != null) {
parameters.putAll(properties);
}
}
测试代码
@Test
public void test03() {
//生成单个节点,这个只能传入一个属性名和属性值
neo4jUtil.createNode("person", "name", "唐僧");
neo4jUtil.createNode("person", "name", "孙悟空");
neo4jUtil.createNode("person", "name", "猪八戒");
neo4jUtil.createNode("person", "name", "沙僧");
}
@Test
public void test04() {
//生成多个节点,传入属性名和属性值的map
Map<String, Object> nodeProperty = new HashMap<>();
nodeProperty.put("name", "雷军");
nodeProperty.put("car", "su7");
neo4jUtil.createNode("小米", nodeProperty);
}
@Test
public void test05() {
Map<String, Object> map = new HashMap<>();
map.put("name","唐僧");
Map<String, Object> map1 = new HashMap<>();
map1.put("name","孙悟空");
Map<String, Object> relationMap = new HashMap<>();
relationMap.put("year","2024");
neo4jUtil.createRelationship("person",map,"person",map1,"徒弟",relationMap);
}
效果达成,解决上篇文章中得问题!!!