Springboot 撞上 NebulaGraph——NGbatis 初体验

简介: NGbatis 是一款针对 NebulaGraph + Spring Boot 的数据库 ORM 框架。借鉴于 MyBatis 的使用习惯进行开发。包含了一些类似于 mybatis-plus 的单表操作,另外还有一些图特有的实体-关系基本操作。

Springboot 撞上 NebulaGraph——NGbatis 初体验

本文首发于 NebulaGraph 公众号 https://mp.weixin.qq.com/s/z56o6AEz1Z4RmS8Zdx6dTA

大家好,我是开源项目 NGbatis 的发起人大叶(CorvusYe@GitHub)。目前 NGbatis 也已成为 NebulaGraph 开源生态项目之一。在过去的 4 个月里,NGbatis 从提交第一行代码以来,已经发布了 3 个版本,正在一步步变得越来越好。感谢一路同行的人们。

这里给大家贴上仓库地址:https://github.com/nebula-contrib/ngbatis,欢迎大家在仓库下方留言提出建议反馈。

一、目前有哪些参与者?

Springboot 撞上 NebulaGraph——NGbatis 初体验

其中,@Szt-1 做了和 Spring Cloud 和 Nacos 的兼容,@liuxiaocs7 完善了文档,@soul-gin 做了 Java 与数据库之间属性别名的映射,@Nicole00 做了项目自动化与代码规范,@wey-gu 提了很多有利于项目发展的建议并做了国际化。@DawnZzzzz@hejiahuichengxuyuan@yarodai@LiuTianyou 则提了不少 issues,issues 让人获得不少灵感。

可以说现阶段的 NGbatis 是使用者与开发者想法碰撞后的共同产物

二、什么是 NGbatis?

NGbatis 是一款针对 NebulaGraph + Spring Boot 的数据库 ORM 框架。借鉴于 MyBatis 的使用习惯进行开发。包含了一些类似于 mybatis-plus 的单表操作,另外还有一些图特有的实体-关系基本操作。

如果是 Java 后端服务的开发人员,相信看到这里,大家对 NGbatis 的用途有了比较清晰的理解。接下来会从几个问题出发,跟读者们介绍 NGbatis:

  • 关于 NGbatis 有哪些思考?
  • NGbatis 能做什么?
  • NGbatis 是怎么实现的?
  • NGbatis 怎么使用?

三、关于 NGbatis 有哪些思考?

  • Q: 最原始的诉求是什么?

    • A: 与 MyBatis 相同,想实现 GQL 与 Java 代码的分离 。
  • Q: 为什么不直接使用 MyBatis 集成?

    • A:

      • MyBatis 遵循 JDBC 规范,而 JDBC 规范更适合于传统数据库,图数据库存在与传统数据库不同的、图特有的结构,如果采用 JDBC 规范,会受到一定局限。
      • 想为图数据库量身定制一款 ORM,随着图数据库的发展,方便拓展。
  • Q: 是否可以基于 JDBC 拓展出 GJDBC 的规范?

    • A: 个人能力有限,不敢想,或许 NebulaGraph 官方可以考虑下。
  • Q: 为什么版本号从 v1.1.0 开始,缺失了 v1.0.0 的版本号?

    • A:

      • 最开始的版本是用来适配 Neo4j,后来选用了 NebulaGraph,保留了一个不曾发布的小版本。
      • 第一次接触的 NebulaGraph 是 v3.1.0,兼容性方面重点放在 v3.1.0+ 的版本

以上,便是开发之初对 NGbatis 的一些方案选择的思考,做了一些取舍,是好处多一些还是坏处多一些,我自己目前也还在纠结中。比如说放弃 JDBC 的规范后也意味着放弃其背后的生态,比如说优秀的第三方连接池方案。

纠结归纠结,既然做了决定,路还是要往下走。开胃菜上完了,也该上正餐了。

四、NGbatis 能做什么?

一个项目诞生最恰当的理由是:想要用它解决一些问题。以解决问题为中心,可以让项目走得更远。NGbatis 的任务就是尽可能地减少日常开发中或重复或繁琐的工作。

  • 在代码里频繁地做“字符串”+”字符串”
  • 一遍一遍地重复处理 ResultSet -> 业务对象
  • 重复写单表基本的增、删、改、查
  • 在集成时,做过多配置,为什么万事就一定是开头难,简单点,集成的方式简单点
  • 需要关注与业务关系不是很密切的 Session 问题

我们生活在一个基础设施相对完善的时代,好处在于问题产生的同时,答案的模型也同时存在,我们需要做的只是在问题与答案之间做适配,这里真诚地对作出贡献的前辈们表示感谢。

以上问题就要求 NGbatis 需要做到以下几点:

  • 开箱即用,实现与 Springboot、Springcloud 的快速集成
  • 实现 GQL 与 Java 代码分离,使用 XML 统一管理
  • 使用模板引擎,解决 GQL 参数拼接繁琐、容易写错的问题
  • 实现 ResultSet 与 Java 对象根据属性名自动转换
  • 单表基本增、删、改、查以及分页
  • 本地 Session 管理,降低资源消耗

方向有了,剩下的就是工程问题了。

五、NGbatis 是怎么实现的?

我们最本质的要求就是:把 GQL 语句执行到 NebulaGraph 当中。我们以带参的 Hello Nebula 为例,即:

Springboot 撞上 NebulaGraph——Ngbatis 初体验

根据最朴素的 Java 开发方法,可以想到的是:先通过 XML 给 GQL 定义一个坐标,再定义一个接口,最后编写一个实现类按坐标读取 GQL 语句,使用模板引擎替换参数。即:

  • XML
<mapper namespace=
        "com.example.dao.TestDao">

    <select id="greet">
        RETURN 'Hello ${ p0 }'
    </select>

</mapper>
  • DAO 接口
package com.example.dao;

public interface TestDao {
  String greet(String who);
}
  • DAO 实现(伪代码)
package com.example.dao;

public class TestDaoImpl implements TestDao {

  @Override
  public String greet(String who) {
    Object[] var2 = new Object[]{who};
    String namespace = "com.example.dao.TestDao";
    String methodName = "greet";
    // 有一个函数,可以完成以下事情:
    // 1. 根据坐标读取 GQL
    // 2. 使用模板引擎完成参数拼接(Beetl)
    // 3. 执行到数据库
    // 4. 转换 ResultSet 形成 业务对象
    return foo( namespace, methodName, var2 );
  }
}

做到这里其实就剩下 foo 怎么编写的问题了。到这里,相信读者们都有自己的思路。大家有兴趣的话可以参考
org.nebula.contrib.ngbatis.proxy.MapperProxy

但这里引入了另一个问题:每个 dao 的方法,写法基本是一样的,又带来了重复的工作,有悖于 NGbatis 的初衷。因此,使用动态代理,从 XML 与 DAO 信息中自动生成 TestDao$Proxy,这边使用的代理方案是基于字节码技术 ASM 来生成。上述的例子生成的字节码反编译后的结果如下:

package com.example.dao;

import org.nebula.contrib.ngbatis.proxy.MapperProxy;

public class TestDao$Proxy implements TestDao {

  @Override
  public String greet(String var1) {
    Object[] var2 = new Object[]{var1};
    return (String) MapperProxy.invoke( "com.example.dao.TestDao", "greet", var2 );
  }
}

因此,开发者便不需要再重复编写诸多 TestDaoImpl,定义好 XML 与 DAO,剩下的工作可以放心地交给 NGbatis。

最后剩下一个问题,参数替换问题:这个问题应该是与开发者关系最为密切的问题。所以,这里不得不提的模板引擎框架:Beetl 是国内流行模板引擎,也是 NGbatis 一个重要的组成部分,链接是官网的 API。

  • 在调用时,将入参 json 化成 nebula-java 可以接收的参数形式(List、Set、Map、字符串、基本类型...):
                                                  {
String hello = dao.greet(“Nebula”);       -->       “p0”: “Nebula”
                                                  }
  • 最后以 XML 内容为模板,进行替换:
RETURN 'Hello ${ p0 }'                  -->        RETURN 'Hello Nebula'

六、全局流程图

Springboot 撞上 NebulaGraph——Ngbatis 初体验

七、NGbatis 该如何集成到自己的 Springboot 项目

  1. 添加依赖
    <dependency>
        <groupId>org.nebula-contrib</groupId>
        <artifactId>ngbatis</artifactId>
        <version>1.1.0-rc</version>
    </dependency>
  1. 配置 NebulaGrpah 数据库
nebula:
  hosts: 127.0.0.1:19669, ip:port, ....
  username: root
  password: nebula
  space: test
  pool-config:
    min-conns-size: 0
    max-conns-size: 10
    timeout: 0
    idle-time: 0
    interval-idle: -1
    wait-time: 0
    min-cluster-health-rate: 1.0
    enable-ssl: false
  1. 添加扫描包以引入 NGbatis bean
@SpringBootApplication(
  exclude={ DataSourceAutoConfiguration.class }, 
  scanBasePackages = {  "org.nebula.contrib", "your.domain" }  )
public class YourSpringbootApplication {

}
  1. 声明主键生成器
import org.nebula.contrib.ngbatis.PkGenerator;
@Component
public class CustomPkGenerator implements PkGenerator {

    @Override
    public <T> T generate(String tagName, Class<T> pkType) {
        Object id = null; // 此处自行对 id 进行设值。
        return (T) id;
    }

}

到此,对于集成工作来说,任务已经完成,剩下就是开发的工作了。

开发人员只需要做三件事:

  1. 定义接口:
package your.domain;

import  org.nebula.contrib.ngbatis.proxy.NebulaDaoBasic;

public interface PersonDao extends NebulaDaoBasic<Person, String> {
    Person selectByName( @Param("name") String param );
}
  1. 在 resources/mapper/PersonDao.xml 中编写 GQL
<mapper namespace="your.domain.PersonDao">
    <select id="selectByName">
        MATCH (n: person)
        WHERE n.person.name == $name
        RETURN n
        LIMIT 1
    </select>
</mapper>
  1. 调用

    1. 注入:

          @Autowired private PersonDao dao;
    2. 调用自定义接口

      Person tom = dao.selectByName("Tom");
      更多文档: 自定义 nGQL
    3. 调用基类接口

        // 不管属性是否为空,如果数据库中已有对应 id 的值,则覆盖
        public void insert( Person person ) {
          dao.insert( person );
        }
      
        // 仅写入非空属性
        public void insertSelective( Person preson ) {
          dao.insertSelective( person );
        }
      
        // 此处,Person 的主键栏 name 为 String ,则入参为 String
        public Person selectById( String id ) {
          return dao.selectById( id );
        }
      
        // 按属性查询
        public List<Person> selectBySelective( Person person ) {
          return dao.selectBySelective( person );
        }
        
      更多文档: 使用基类读写

八、尾声

以上就是本次交流的全部内容。如果 NGbatis 实现方式也是你喜欢的,issue、pr、star 都是 ok 的。如果对项目感兴趣,也可以参与到开发中来,从中获得成就感。仓库地址:https://github.com/nebula-contrib/ngbatis

最后,希望 NGbatis 能给越来越多的开发者带来开发上的便利。


谢谢你读完本文 (///▽///)

NebulaGraph Desktop,Windows 和 macOS 用户安装图数据库的绿色通道,10s 拉起搞定海量数据的图服务。通道传送门:http://c.nxw.so/blVC6

想看源码的小伙伴可以前往 GitHub 阅读、使用、(^з^)-☆ star 它 -> GitHub;和其他的 NebulaGraph 用户一起交流图数据库技术和应用技能,留下「你的名片」一起玩耍呢~

相关实践学习
阿里云图数据库GDB入门与应用
图数据库(Graph Database,简称GDB)是一种支持Property Graph图模型、用于处理高度连接数据查询与存储的实时、可靠的在线数据库服务。它支持Apache TinkerPop Gremlin查询语言,可以帮您快速构建基于高度连接的数据集的应用程序。GDB非常适合社交网络、欺诈检测、推荐引擎、实时图谱、网络/IT运营这类高度互连数据集的场景。 GDB由阿里云自主研发,具备如下优势: 标准图查询语言:支持属性图,高度兼容Gremlin图查询语言。 高度优化的自研引擎:高度优化的自研图计算层和存储层,云盘多副本保障数据超高可靠,支持ACID事务。 服务高可用:支持高可用实例,节点故障迅速转移,保障业务连续性。 易运维:提供备份恢复、自动升级、监控告警、故障切换等丰富的运维功能,大幅降低运维成本。 产品主页:https://www.aliyun.com/product/gdb
目录
相关文章
|
SpringCloudAlibaba Kubernetes Java
Istio初体验:使用Spring Boot+gRPC构建微服务并部署
Istio初体验:使用Spring Boot+gRPC构建微服务并部署
616 0
|
NoSQL Java 关系型数据库
【Mongodb - 初体验】SpringBoot整合Mongodb
分享springboot整合Mongodb的初体验,从安装到整合与使用,初步掌握MongoDB的初使用。
162 0
【Mongodb - 初体验】SpringBoot整合Mongodb
|
SQL XML Java
【SpringBoot DB 系列】Jooq 初体验
java 环境中,说到数据库的操作,我们通常会想到的是 mybatis 或者 hibernate,今天给大家介绍一个国内可能用得不太多的操作方式 JOOQ,一款基于 Java 访问关系型数据库的工具包,轻量,简单,并且足够灵活的 ORM 框架 本文将各位小伙伴演示一下 jooq 集成 springboot 的姿势
629 0
|
IDE Java Maven
Java编程:Spring boot初体验
Java编程:Spring boot初体验
129 0
|
XML Java 数据格式
Spring Boot(01)——初体验
Spring Boot初体验 Spring Boot的理念是抛弃XML配置(当然,如果你想采用XML配置也是可以的,但是Spring Boot推荐使用基于Java的配置),采用纯Java配置和properties或yml文件配置,通过提供一系列的Starter可以使开发者快速的搭建起一套开发环境。
1501 0
|
IDE Java 开发工具
SpringBoot-01-之初体验
一.创建一个项目:IDE为IDEA 创建流程 二.新建一个Controller类: toly1994.com.toly01.controller.
925 0
|
1月前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 实现动态路由和菜单功能,快速搭建前后端分离的应用框架
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 实现动态路由和菜单功能,快速搭建前后端分离的应用框架。首先,确保开发环境已安装必要的工具,然后创建并配置 Spring Boot 项目,包括添加依赖和配置 Spring Security。接着,创建后端 API 和前端项目,配置动态路由和菜单。最后,运行项目并分享实践心得,包括版本兼容性、安全性、性能调优等方面。
143 1
|
18天前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。首先,创建并配置 Spring Boot 项目,实现后端 API;然后,使用 Ant Design Pro Vue 创建前端项目,配置动态路由和菜单。通过具体案例,展示了如何快速搭建高效、易维护的项目框架。
95 62
|
16天前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个前后端分离的应用框架,实现动态路由和菜单功能
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个前后端分离的应用框架,实现动态路由和菜单功能。首先,确保开发环境已安装必要的工具,然后创建并配置 Spring Boot 项目,包括添加依赖和配置 Spring Security。接着,创建后端 API 和前端项目,配置动态路由和菜单。最后,运行项目并分享实践心得,帮助开发者提高开发效率和应用的可维护性。
34 2
|
18天前
|
JavaScript Java 项目管理
Java毕设学习 基于SpringBoot + Vue 的医院管理系统 持续给大家寻找Java毕设学习项目(附源码)
基于SpringBoot + Vue的医院管理系统,涵盖医院、患者、挂号、药物、检查、病床、排班管理和数据分析等功能。开发工具为IDEA和HBuilder X,环境需配置jdk8、Node.js14、MySQL8。文末提供源码下载链接。