Spring Boot整合Neo4j实现增删改查

  1. 一、pom文件如下
  2. 二、配置文件:application.yml
  3. 三、启动类 Neo4jApplication
  4. 四、项目结构
  5. 五、增删改查
  6. 六、API测试

演示环境:

Neo4j: 3.5.5

JDK: 1.8

SpringBoot: 2.3.4

Maven: 3.8

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

一、pom文件如下

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.3.4.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>

<properties>
    <maven.compiler.source>8</maven.compiler.source>
    <maven.compiler.target>8</maven.compiler.target>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <maven.test.skip>true</maven.test.skip>
    <spring-boot.version>2.3.4.RELEASE</spring-boot.version>
    <commons-lang3.version>3.12.0</commons-lang3.version>
    <hutool-all.version>5.8.6</hutool-all.version>
</properties>

<dependencies>
    <!--web依赖-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- spring boot 服务监控-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    <!-- aop -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-aop</artifactId>
    </dependency>
    <!--springboot读取自定义配置依赖-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-configuration-processor</artifactId>
        <optional>true</optional>
    </dependency>
    <!-- 测试依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
        <exclusions>
            <exclusion>
                <groupId>org.junit.vintage</groupId>
                <artifactId>junit-vintage-engine</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <!-- commons-lang3 -->
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-lang3</artifactId>
        <version>${commons-lang3.version}</version>
    </dependency>
    <!-- lombok -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <scope>provided</scope>
    </dependency>
    <!-- hutool工具 -->
    <dependency>
        <groupId>cn.hutool</groupId>
        <artifactId>hutool-all</artifactId>
        <version>${hutool-all.version}</version>
    </dependency>
    <!--整合neo4j-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-neo4j</artifactId>
    </dependency>
</dependencies>

<build>
    <!--配置jar包名称-->
    <finalName>ioms-data-service</finalName>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <version>${spring-boot.version}</version>
            <configuration>
                <includeSystemScope>true</includeSystemScope>
                <fork>true</fork>     <!--fork :  如果没有该项配置devtools不会起作用,即应用不会restart -->
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.8.1</version>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
            </configuration>
        </plugin>
    </plugins>
</build>

二、配置文件:application.yml

server:
  # 程序启动端口
  port: 1180
spring:
  data:
    neo4j:
      # neo4j用户名
      username: neo4j
      # neo4j密码
      password: 123456
      # 程序链接数据库地址
      uri: bolt://192.168.6.131:7687
logging:
  level:
    # 打印neo4j日志
    org.springframework.data.neo4j: debug

三、启动类 Neo4jApplication

@Slf4j
@SpringBootApplication
public class Neo4jApplication {
    public static void main(String[] args) {
        SpringApplication.run(Neo4jApplication.class, args);
        log.info("neo4j-demo启动成功");
    }
}

四、项目结构

项目结构

五、增删改查

这里演示简单的单表增删改查操作,关于节点的关系维护,后面再做讲解。

数据实体类:CompanyEntryNode

主键:uuid,通过@Id标识,通过@GeneratedValue在插入数据库时自动生成

@NodeEntity(value = "CompanyNode", label = "公司节点") // value:节点的Lable,label:用户描述该类
@Data
public class CompanyEntryNode {
    @Id
    @GeneratedValue(strategy = UuidStrategy.class) // 将字段ID标识为主键,配合 @GeneratedValue 自动生成id值, 生成策略默认是 InternalIdStrategy.class 生成的Long值
    private String uuid;
    /**
     * 名称
     */
    private String name;

    /**
     * 公司表id
     */
    private String companyId;

    /**
     * 类型
     */
    private String type;

    /**
     * 别名
     */
    private String aliasName;
    /**
     * 行业
     */
    private String industry;

    /**
     * 经营范围
     */
    private String scope;

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

    /**
     * 图片路径
     */
    private String imagePath;
    /**
     * 状态 0草稿 1已审核
     */
    private String status;

    /**
     * 修改人Id
     */
    private String modifyUserId;

    /**
     * 修改时间
     */
    private Long modifyTime;

    /**
     * 创建人Id
     */
    private String createUserId;

    /**
     * 创建时间
     */
    private Long createTime;
}

持久层:CompanyEntryRepository

通过继承 Neo4jRepository<Entity, ID>, spring-data-neo4j 已经替我们完成大部分的增删改查的操作了,但是仍不能满足复杂查询,删除的需要。所以这里也通过 Cypher 语句以及传参的形式完成复杂需求的开发。

@Repository
public interface CompanyEntryRepository extends Neo4jRepository<CompanyEntryNode, String> { // <实体类, 主键>

    /**
     * 根据公司id判断 公司是否已经存在
     * match(n:CompanyNode {companyId: "id1"}) return n.aliasName;
     * @param companyId 查询参数companyId
     * @return
     */
    @Query("match(n:CompanyNode {companyId: {companyId}}) return n.introduction")
    List<String> existsByCompanyId(String companyId);

    /**
     * 根据companyId删除数据
     * @param companyId 查询参数companyId
     * @return
     */
    @Query("match(n:CompanyNode {companyId: {companyId}}) delete n")
    void deleteByCompanyId(String companyId);

    /**
     * 删除实体类的某个属性
     * @param companyId 查询参数companyId
     * @return
     */
    @Query("match(n:CompanyNode {companyId: {companyId}}) remove n.type")
    void removeTypeByCompanyId(String companyId);
}

Service层:CompanyEntryService、CompanyEntryServiceImpl、

通过调用 CompanyEntryRepository 完成数据的操作

public interface CompanyEntryService {

    /**
     * 新增数据
     * @param entryNode
     * @return
     */
    R save(CompanyEntryNode entryNode);

    /**
     * 根据主键ID,主键:uuid
     * @param uuid
     * @return
     */
    R deleteById(String uuid);

    /**
     * 根据 companyId 属性删除数据
     * @param companyId
     * @return
     */
    R deleteByCompanyId(String companyId);

    /**
     * 删除实体类的type属性
     * @param companyId 查询参数companyId
     * @return
     */
    R removeType(String companyId);

    /**
     * 数据更新
     * @param entryNode
     * @return
     */
    R update(CompanyEntryNode entryNode);

    /**
     * 获取所有数据
     *
     * @return
     */
    List<CompanyEntryNode> getAll();

    /**
     * 根据companyId查询
     * @param companyId
     * @return
     */
    List<String> getByCompanyId(String companyId);

}


@Slf4j
@Service
public class CompanyEntryServiceImpl implements CompanyEntryService {
    @Autowired
    private CompanyEntryRepository companyEntryRepository;


    @Override
    public R save(CompanyEntryNode entryNode) {
        CompanyEntryNode data = companyEntryRepository.save(entryNode);
        if (ObjectUtils.isEmpty(data)) return new R(false, CommonConstants.FAIL, "操作失败");

        return new R(data);
    }

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

    @Override
    public R deleteByCompanyId(String companyId) {
        try {
            companyEntryRepository.deleteByCompanyId(companyId);
        } catch (Exception e) {
            e.printStackTrace();
            return new R(false, CommonConstants.FAIL, "操作失败");
        }
        return new R();
    }


    @Override
    public R removeType(String companyId) {
        companyEntryRepository.removeTypeByCompanyId(companyId);
        return new R();
    }

    @Override
    public R update(CompanyEntryNode entryNode) {
        if (StringUtils.isEmpty(entryNode.getUuid())) return new R(false, CommonConstants.FAIL, "操作失败,参数异常");

        CompanyEntryNode data = companyEntryRepository.save(entryNode);
        return new R(data);
    }

    @Override
    public List<CompanyEntryNode> getAll() {
        Iterable<CompanyEntryNode> all = companyEntryRepository.findAll();
        List<CompanyEntryNode> companyEntryNodes = new ArrayList<>();
        CollectionUtil.addAll(companyEntryNodes, all);
        return companyEntryNodes;
    }

    @Override
    public List<String> getByCompanyId(String companyId) {
        List<String> names = companyEntryRepository.existsByCompanyId(companyId);
        return names;
    }
}

Controller层:CompanyEntryController

对Service层调用

@Slf4j
@RestController
@RequestMapping(value = "/companyEntry")
public class CompanyEntryController {
    @Autowired
    private CompanyEntryService companyEntryService;

    /**
     * 新增数据
     * @param node
     * @return
     */
    @PostMapping("/save")
    public R save(@RequestBody CompanyEntryNode node) {
        R result = companyEntryService.save(node);
        return result;
    }

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

    /**
     * 根据属性查询后删除
     * @param companyId 查询条件companyId
     * @return
     */
    @DeleteMapping("/deleteByParam")
    public R deleteByParam(@RequestParam(value = "companyId", required = false) String companyId) {
        R result = companyEntryService.deleteByCompanyId(companyId);
        return result;
    }

    /**
     * 删除实体类的某个属性字段
     * @param companyId 查询条件companyId
     * @return
     */
    @GetMapping("/removeType")
    public R removeType(@RequestParam(value = "companyId", required = false) String companyId) {
        R result = companyEntryService.removeType(companyId);
        return result;
    }

    /**
     * 数据更新
     * @param node
     * @return
     */
    @PostMapping("/update")
    public R update(@RequestBody CompanyEntryNode node) {
        R result = companyEntryService.update(node);
        return result;
    }

    /**
     * 获取所有Company数据
     * @return
     */
    @GetMapping("/getAll")
    public R<List<CompanyEntryNode>> getAll() {
        List<CompanyEntryNode> list = companyEntryService.getAll();
        return new R(list);
    }

    /**
     * 根据CompanyId查询
     * @param companyId
     * @return
     */
    @GetMapping("/getNameByCompanyId")
    public R<List<String>> getNameByCompanyId(@RequestParam(value = "companyId", required = false) String companyId) {
        List<String> names = companyEntryService.getByCompanyId(companyId);
        return new R<>(names);
    }
}

六、API测试

01-新增数据

{
    "name": "肯德基",
    "companyId": "f1",
    "type": "fast food",
    "aliasName": "肯德基",
    "industry": "food",
    "introduction": "做快餐肯德基"
}

新增数据

新增数据

02-根据主键删除

02-根据主键删除

03-根据属性查询后删除

03-根据属性查询后删除

04-删除实体类的某个属性字段

这里将匹配到Company对象的type属性置为null

image-20241107204124647

05-更新数据

{
    "uuid": "d7de403d-0262-4589-9116-87dde707aae4",
    "name": "肯德基",
    "companyId": "f1",
    "type": "fast food",
    "aliasName": "肯德基",
    "industry": "food",
    "introduction": "做快餐肯德基更新了~~~~"
}

05-更新数据

06-查询所有数据

06-查询所有数据

07-根据参数查询

07-根据参数查询

到此基于Spring Boot对Neo4j的增删该查就完成了,后面再更新如果通过Java对节点间的关系进行维护。

参考链接

https://www.zhihu.com/column/c_1364222745673261056

https://blog.csdn.net/qq_35754073/article/details/137144515


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