Spring Boot对Neo4j节点关系的增删改查

  1. 一、代码实现
  2. 二、API测试

演示环境:

Neo4j: 3.5.5

JDK: 1.8

SpringBoot: 2.3.4

Maven: 3.8

如何搭建neo4j数据库,参考:Docker部署Neo4j并导入CSV数据

Spring Boot 对Neo4j单节点数据的增删改查:Spring Boot整合Neo4j实现增删改查

本篇主要介绍Spring Boot 对 Neo4j 节点之间关系的增删改查操作。例如 “肯德基” 是一家公司,“麦辣鸡腿堡” 就是一个具体的产品,那么“肯德基” 与 “麦辣鸡腿堡” 就是一种生产关系。如何对这种关系进行操作,就是本篇要讲述的内容。

一、代码实现

Model层

@NodeEntity(value = "ProductNode", label = "产品节点") // value:节点的Lable,label:用于描述该类
@Data
public class ProductEntryNode {
    @Id
    @GeneratedValue(strategy = UuidStrategy.class) // 将字段ID标识为主键,配合 @GeneratedValue 自动生成id值, 生成策略默认是 InternalIdStrategy.class 生成的Long值
    private String productEntryId;

    /**
     * 词条名称
     */
    private String name;

    /**
     * 模板id
     */
    private String templateId;

    /**
     * 词条类型  1:产品种类 2:产品类型 3:产品单元
     */
    private String type;
    /**
     * 别名
     */
    private String aliasName;

    /**
     * 简介
     */
    private String introduction;
}


// 公司->生产 产品关系
// 指定关系名称为Production
@Data
@RelationshipEntity(type = "Production")
public class ProductionRelationship {
    @Id
    @GeneratedValue(strategy = UuidStrategy.class) // 将字段ID标识为主键,配合 @GeneratedValue 自动生成id值, 生成策略默认是 InternalIdStrategy.class 生成的Long值
    private String uuid;

    @StartNode // 表示节点指向的起点
    private CompanyEntryNode startNode;

    @EndNode // 表示节点指向的终点
    private ProductEntryNode endNode;

    /**
     * 收入占比
     */
    private String incomeProportion;

    /**
     * 毛利率
     */
    private String productGross;

    /**
     * 产品单价
     */
    private String productPrice;

    /**
     * 产能
     */
    private String capacity;

    /**
     * 产能利用率
     */
    private String capacityRatio;

    /**
     * 产能占比
     */
    private String capacityProportion;
}

自定义查询结果集

用于接收Spring-Data-Neo4j 自定义返回的结果对象, 实体类必须添加 @QueryResult 注解

@Data
@QueryResult // 此注解用于返回Spring-data-neo4j查询返回自定义结果集
public class RelationshipDto {

    private String uuid;

    /**
     * 收入占比
     */
    private String incomeProportion;

    /**
     * 毛利率
     */
    private String productGross;

    /**
     * 产品单价
     */
    private String productPrice;

}

持久层

@Repository
public interface ProductEntryRepository extends Neo4jRepository<ProductEntryNode, String> {

    /**
     * 根据产品别名查询产品数据集
     * @param aliasName 产品别名
     * @return
     */
    @Query("match(n:ProductNode) where n.aliasName = {aliasName} return n")
    List<ProductEntryNode> getDataByQuery(@Param("aliasName") String aliasName);
}


@Repository
public interface ProductionRelationshipRepository extends Neo4jRepository<ProductionRelationship, String> {

    /**
     * 根据产品获取供应商
     *
     * 经过测试,返回结果无法映射自定义DTO对象,这里需要用Map接收自定以返回数据
     * @param productEntryId
     * @return
     */
    @Query("match (c:CompanyNode)-[:Production]->(p:ProductNode) where p.productEntryId = {productEntryId} return c.companyId as companyId, c.name as name ")
    List<Map<String, Object>> getCompanyByProductId(@Param("productEntryId") String productEntryId);

    /**
     * 根据产品获取供应商
     * @param aliasName 产品名称
     * @return
     */
    @Query("match (c:CompanyNode)-[:Production]->(p:ProductNode) where p.aliasName = {aliasName} return c")
    List<CompanyEntryNode> getCompanyByProductName(@Param("aliasName") String aliasName);

    /**
     * 根据参数查询并返回关系数据
     * match relationship = (c:CompanyNode)-[r:Production]->(p:ProductNode) where type(r) = "Production" and c.aliasName = "肯德基" and p.aliasName = "麦辣鸡" return relationship limit 1;
     * @param typeName 关系类型名称
     * @param companyName 公司名称
     * @param productName 产品名称
     * @return
     */
    @Query("match relationship = (c:CompanyNode)-[r]->(p:ProductNode) where type(r) = {typeName} and c.aliasName = {companyName} and p.aliasName = {productName} return relationship limit 1")
    ProductionRelationship getRelationshipByParam(@Param("typeName") String typeName, @Param("companyName") String companyName, @Param("productName") String productName);

    /**
     * 根据产品名称和公司名称获取之间的关系,返回自定义结果集
     * match relationship =  (p:ProductNode {aliasName: "麦辣鸡"})-[r:Production]-(c:CompanyNode {aliasName: "肯德基"}) return relationship;
     * @param productName 产品名称
     * @param companyName 公司名称
     * @return
     */
    @Query("match (p:ProductNode {aliasName: {productName}})-[r:Production]-(c:CompanyNode {aliasName: {companyName}}) return r.uuid as uuid, r.incomeProportion as incomeProportion, r.productGross as productGross, r.productPrice as productPrice")
    List<RelationshipDto> getRelationshipByAliasName(@Param("productName") String productName, @Param("companyName") String companyName);
}

注意: 最后一个查询语句返回的是自定义结果集 RelationshipDto , 查询出的属性都需要 as ***

Service层

public interface ProductEntryService {

    /**
     * 保存产品数据
     * @param node
     * @return
     */
    R<ProductEntryNode> save(ProductEntryNode node);

    /**
     * 根据主键删除
     * @param uuid
     * @return
     */
    R deleteById(String uuid);


    /**
     * 根据产品别名查询产品数据集
     * @param aliasName 产品别名
     * @return
     */
    List<ProductEntryNode> getDataByQuery(String aliasName);
}



public interface ProductionRelationshipService {

    /**
     * 添加公司产品 关系
     * @param startNode 公司节点
     * @param toNode 产品节点
     * @param incomeProportion 收入占比
     * @param productGross 毛利率
     * @param productPrice 产品单价
     * @return
     */
    ProductionRelationship addProductionRelationship(CompanyEntryNode startNode, ProductEntryNode toNode, String incomeProportion, String productGross, String productPrice);


    /**
     * 关联公司产品关系
     * @param startNodeId 公司节点唯一标识
     * @param toNodeId 产品唯一标识
     * @param incomeProportion 收入占比
     * @param productGross 毛利率
     * @param productPrice 产品单价
     * @return
     */
    ProductionRelationship addProductionRelationship(String startNodeId, String toNodeId, String incomeProportion, String productGross, String productPrice);

    /**
     * 获取产品的供应商公司
     *
     * @param productEntryId
     * @return
     */
    List<CompanyDto> getCompanyByProductId(String productEntryId);

    /**
     * 获取产品的供应商公司
     *
     * @param aliasName 产品名称
     * @return
     */
    List<CompanyEntryNode> getCompanyByProductName(String aliasName);

    /**
     * 删除所有节点关系
     * @return
     */
    R deleteAllRelationship();

    /**
     * 根据参数查询并返回关系数据
     * @param typeName 关系类型名称
     * @param companyName 公司名称
     * @param productName 产品名称
     * @return
     */
    ProductionRelationship getRelationshipByParam(String typeName, String companyName, String productName);

    /**
     * 根据产品名称和公司名称获取之间的关系
     * @param productName 产品名称
     * @param companyName 公司名称
     * @return
     */
    List<RelationshipDto> getRelationshipByAliasName(String productName, String companyName);
}



@Slf4j
@Service
public class ProductEntryServiceImpl implements ProductEntryService {

    @Autowired
    private ProductEntryRepository productEntryRepository;

    @Override
    public R<ProductEntryNode> save(ProductEntryNode node) {
        ProductEntryNode entryNode = productEntryRepository.save(node);
        return new R<>(entryNode);
    }

    @Override
    public R deleteById(String uuid) {
        productEntryRepository.deleteById(uuid);
        return new R();
    }

    @Override
    public List<ProductEntryNode> getDataByQuery(String aliasName) {
        List<ProductEntryNode> list = productEntryRepository.getDataByQuery(aliasName);
        return list;
    }
}



@Slf4j
@Service
public class ProductionRelationshipServiceImpl implements ProductionRelationshipService {
    @Autowired
    private ProductionRelationshipRepository productionRelationshipRepository;

    @Autowired
    private CompanyEntryRepository companyEntryRepository;

    @Autowired
    private ProductEntryRepository productEntryRepository;

    @Autowired
    private ObjectMapper objectMapper;

    @Override
    public ProductionRelationship addProductionRelationship(CompanyEntryNode startNode, ProductEntryNode toNode, String incomeProportion, String productGross, String productPrice) {
        ProductionRelationship productionRelationship = new ProductionRelationship();
        productionRelationship.setStartNode(startNode);
        productionRelationship.setEndNode(toNode);
        productionRelationship.setIncomeProportion(incomeProportion);
        productionRelationship.setProductGross(productGross);
        productionRelationship.setProductPrice(productPrice);
        ProductionRelationship save = productionRelationshipRepository.save(productionRelationship);
        return save;
    }

    @Override
    public ProductionRelationship addProductionRelationship(String startNodeId, String toNodeId, String incomeProportion, String productGross, String productPrice) {
        ProductionRelationship relationship = null;
        Optional<CompanyEntryNode> companyOptional = companyEntryRepository.findById(startNodeId);
        Optional<ProductEntryNode> productOptional = productEntryRepository.findById(toNodeId);
        if (companyOptional.isPresent() && productOptional.isPresent()) {
            relationship = addProductionRelationship(companyOptional.get(), productOptional.get(), incomeProportion, productGross, productPrice);
        }
        return relationship;
    }

    @Override
    public List<CompanyDto> getCompanyByProductId(String productEntryId) {
        List<CompanyDto> companyDtos = new ArrayList<>();
        List<Map<String, Object>> maps = productionRelationshipRepository.getCompanyByProductId(productEntryId);
        try {
            String json = objectMapper.writeValueAsString(maps);
            companyDtos = objectMapper.readValue(json, new TypeReference<List<CompanyDto>>() {});
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return companyDtos;
    }

    @Override
    public List<CompanyEntryNode> getCompanyByProductName(String aliasName) {
        List<CompanyEntryNode> list = productionRelationshipRepository.getCompanyByProductName(aliasName);
        return list;
    }

    @Override
    public R deleteAllRelationship() {
        productionRelationshipRepository.deleteAll();
        return new R();
    }

    @Override
    public ProductionRelationship getRelationshipByParam(String typeName, String companyName, String productName) {
        ProductionRelationship relationship = productionRelationshipRepository.getRelationshipByParam(typeName, companyName, productName);
        return relationship;
    }

    @Override
    public List<RelationshipDto> getRelationshipByAliasName(String productName, String companyName) {
        List<RelationshipDto> relationship = productionRelationshipRepository.getRelationshipByAliasName(productName, companyName);
        return relationship;
    }
}

Controller层

@Slf4j
@RestController
@RequestMapping(value = "/productEntry")
public class ProductEntryController {

    @Autowired
    private ProductEntryService productEntryService;

    /**
     * 保存产品数据
     * @param node 参数列表
     * @return
     */
    @PostMapping("/save")
    public R<ProductEntryNode> save(@RequestBody ProductEntryNode node) {
        R<ProductEntryNode> result = productEntryService.save(node);
        return result;
    }

    /**
     * 根据id删除
     * @param uuid
     * @return
     */
    @DeleteMapping("/deleteById")
    public R deleteById(@RequestParam(value = "uuid", required = false) String uuid) {
        R result = productEntryService.deleteById(uuid);
        return result;
    }

    /**
     * 根据产品别名查询产品数据集
     * @param aliasName 产品别名
     * @return
     */
    @GetMapping("/getDataByQuery")
    public R<List<ProductEntryNode>> getDataByQuery(@RequestParam(value = "aliasName", required = false) String aliasName) {
        List<ProductEntryNode> list = productEntryService.getDataByQuery(aliasName);
        return new R<>(list);
    }
}



@Slf4j
@RestController
@RequestMapping(value = "/productionRelationship")
public class ProductionRelationshipController {
    @Autowired
    private ProductionRelationshipService productionRelationshipService;

    /**
     * 关联公司产品关系
     * @param companyUuid 公司节点唯一标识
     * @param productId 产品唯一标识
     * @param incomeProportion 收入占比
     * @param productGross 毛利率
     * @param productPrice 产品单价
     * @return
     */
    @GetMapping("/addRelationship")
    public R addRelationship(@RequestParam(value = "companyUuid", required = false) String companyUuid,
                             @RequestParam(value = "productId", required = false) String productId,
                             @RequestParam(value = "incomeProportion", required = false) String incomeProportion,
                             @RequestParam(value = "productGross", required = false) String productGross,
                             @RequestParam(value = "productPrice", required = false) String productPrice) {
        ProductionRelationship relationship = productionRelationshipService.addProductionRelationship(companyUuid, productId, incomeProportion, productGross, productPrice);
        return new R(relationship);
    }

    /**
     * 根据产品获取供应商信息
     * @param productId 产品唯一标识
     * @return
     */
    @GetMapping("/getCompanyByProductId")
    public R<List<CompanyDto>> getCompanyByProductId(@RequestParam(value = "productId", required = false) String productId) {
        List<CompanyDto> companyDtos = productionRelationshipService.getCompanyByProductId(productId);
        return new R(companyDtos);
    }

    /**
     * 根据产品名称获取供应商信息
     * @param productName 产品名称
     * @return
     */
    @GetMapping("/getCompanyByProductName")
    public R<List<CompanyEntryNode>> getCompanyByProductName(@RequestParam(value = "productName", required = false) String productName) {
        List<CompanyEntryNode> companyDtos = productionRelationshipService.getCompanyByProductName(productName);
        return new R(companyDtos);
    }

    /**
     * 删除所有节点关系
     * @return
     */
    @DeleteMapping("/deleteAllRelationship")
    public R deleteAllRelationship() {
        R result = productionRelationshipService.deleteAllRelationship();
        return result;
    }

    /**
     * 根据参数查询并返回关系数据
     * @param typeName 关系类型名称
     * @param companyName 公司名称
     * @param productName 产品名称
     * @return
     */
    @GetMapping("/getRelationshipByParam")
    public R<ProductionRelationship> getRelationshipByParam(@RequestParam(value = "typeName", required = false) String typeName,
                                                            @RequestParam(value = "companyName", required = false) String companyName,
                                                            @RequestParam(value = "productName", required = false) String productName) {
        ProductionRelationship relationship = productionRelationshipService.getRelationshipByParam(typeName, companyName, productName);
        return new R<>(relationship);
    }

    /**
     * 根据产品名称和公司名称获取之间的关系
     * @param productName 产品名称
     * @param companyName 公司名称
     * @return
     */
    @GetMapping("/getRelationshipByAliasName")
    public R<List<RelationshipDto>> getRelationshipByAliasName(@RequestParam(value = "productName", required = false) String productName,
                                                                      @RequestParam(value = "companyName", required = false) String companyName) {
        List<RelationshipDto> relationship = productionRelationshipService.getRelationshipByAliasName(productName, companyName);
        return new R<>(relationship);
    }
}

二、API测试

将公司与产品建立关系

将公司与产品建立关系

节点关系

删除所有节点关系

删除所有节点关系

根据产品id获取供应商信息

根据产品id获取供应商信息

根据产品名称获取供应商

根据产品名称获取供应商

根据参数查询并返回关系数据

根据参数查询并返回关系数据

根据参数查询并返回关系数据

查询关系数据,返回自定义结果集

查询关系数据,返回自定义结果集


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 george_95@126.com