本文首发于 Nebula Graph Community 公众号

我最近注意到很多同学对于 ORM 框架的需求比较迫切,而且有热心的同学已经捐赠了自己开发的项目,Nebula 社区也在 working on it。下面主要介绍一下我们在使用 MyBatis 操作 Nebula Graph 方面的一些经验,希望能够帮助到大家。

MyBatis

Java 开发的同学想必对 MyBatis 都比较熟悉了。MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射,并且免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。

实现途径

主要通过 MyBatis 结合 nebula-jdbc 来实现参数返回值映射以及语句执行。

Demo 示例

完整代码参见 GitHub

Nebula Schema

CREATE SPACE basketballplayer(partition_num=10,replica_factor=1,vid_type=fixed_string(32));
CREATE TAG IF NOT EXISTS player(name string, age int);
CREATE EDGE IF NOT EXISTS follow(degree int);

工程结构

application.yaml

spring:
datasource:
driver-class-name: com.vesoft.nebula.jdbc.NebulaDriver
url: jdbc:nebula://localhost:9669/basketballplayer
username: nebula
password: nebula
hikari:
maximum-pool-size: 20
mybatis:
mapper-locations: classpath:mapper/*.xml

DO

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class PlayerDO {
/**
* vid
*/
private String id;
private String name;
private Long age;
}

Dao

public interface PlayerDao {

    int insert(PlayerDO entity);

    int update(PlayerDO entity);

    int insertBatch(List<PlayerDO> batch);

    PlayerDO select(String id);

    List<PlayerDO> selectBatch(List<String> batch);

    int delete(String id);

    int deleteBatch(List<String> batch);

    //以上代码自动生成

    PlayerDO selectReturnV(String id);
}

Mapper

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.dao.PlayerDao">
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="com.example.pojo.PlayerDO">
<result column="id" property="id" jdbcType="VARCHAR"/>
<result column="name" property="name" jdbcType="VARCHAR"/>
<result column="age" property="age" jdbcType="BIGINT"/>
</resultMap> <!-- 插入点或边 -->
<insert id="insert" parameterType="com.example.pojo.PlayerDO">
insert vertex `player` (
<trim suffixOverrides=",">
<if test="name != null">
name,
</if>
<if test="age != null">
age,
</if>
</trim>
) values #{id} :(
<trim suffixOverrides=",">
<if test="name != null">
#{name},
</if>
<if test="age != null">
#{age},
</if>
</trim>
)
</insert> <!-- 批量插入点或边-->
<insert id="insertBatch" parameterType="com.example.pojo.PlayerDO">
insert vertex `player`
<trim prefix="(" suffix=")" suffixOverrides=",">
name,
age,
</trim>
values
<foreach collection="list" item="item" separator=",">
#{item.id} :
<trim prefix="(" suffix=")" suffixOverrides=",">
#{item.name},
#{item.age},
</trim>
</foreach>
</insert> <!-- 更新点或边 -->
<update id="update" parameterType="com.example.pojo.PlayerDO">
UPDATE vertex ON `player` #{id}
<trim prefix="set" suffixOverrides=",">
<if test="name != null">
name = #{name},
</if>
<if test="age != null">
age = #{age},
</if>
</trim>
</update> <!-- 查询点 -->
<select id="select" resultType="com.example.pojo.PlayerDO">
match (v:`player`) where id(v) == #{id} return
<trim suffixOverrides=",">
id(v) as id,
v.name as name,
v.age as age,
</trim>
</select> <!-- 批量查询点 -->
<select id="selectBatch" resultType="com.example.pojo.PlayerDO">
match (v:`player`) where id(v) in [
<foreach collection="list" item="item" separator=",">
#{item}
</foreach>
] return
<trim suffixOverrides=",">
id(v) as id,
v.name as name,
v.age as age,
</trim>
</select> <!-- 删除点或边 -->
<delete id="delete" parameterType="java.lang.String">
delete vertex #{id}
</delete> <!-- 批量删除点或边 -->
<delete id="deleteBatch"
parameterType="java.lang.String">
delete vertex
<foreach collection="list" item="item" separator=",">
#{item}
</foreach>
</delete>
<!--以上代码自动生成--> <select id="selectReturnV" resultMap="BaseResultMap">
match (v:`player`) where id(v) == #{id} return v
</select>
</mapper>

Tag 操作

@SpringBootTest
public class PlayerDaoTest { @Resource
private PlayerDao playerDao; @Test
public void operation() {
//insert
PlayerDO player = PlayerDO.builder().id("daiyi").name("daiyi").age(22l).build();
playerDao.insert(player);
//insertBatch
PlayerDO playerBatch = PlayerDO.builder().id("daiyi").name("daiyi").age(22l).build();
PlayerDO joe = PlayerDO.builder().id("joe").name("joe").age(24l).build();
playerDao.insertBatch(Lists.newArrayList(playerBatch, joe));
//update
playerDao.update(PlayerDO.builder().id("daiyi").name("daiyiupdate").build());
//select
PlayerDO playerDO = playerDao.select("daiyi");
//selectBatch
List<PlayerDO> players = playerDao.selectBatch(Lists.newArrayList("daiyi", "joe"));
//selectReturnV
playerDao.selectReturnV("daiyi");
//delete
playerDao.delete("daiyi");
//deleteBatch
playerDao.deleteBatch(Lists.newArrayList("daiyi", "joe"));
}
}

Edge 及 Path 操作

篇幅有限,详情可以参见github

版本适配

目前仅支持了 Nebula 2.5 版本,后续版本的支持还在适配中。

总结

优点

  • 使用简单,消除了使用 JDBC 或 nebula-client 带来的冗余代码。
  • 可以使用配套连接池管理连接,并且可以与 Spring Boot 无缝衔接。
  • nGQL 与代码解耦,方便管理。
  • 大量便捷标签,免除了代码拼接语句的烦恼。

存在的问题

  • 针对返回值为 Vertex(类似MATCH v RETURN v)、Edge、无属性 Path 的类型目前采用在 MyBatis 中的 Interceptor 做拦截处理,也能满足使用。但这种实现方式感觉不是很好,后期有待优化。
  • 对于返回值类型为带属性 Path、多 Tag 查询以及 GET SUBGRAPH 语句的情况,因为返回的结果中实体以及边的类型可能有多种,目前没有想到比较好的映射方式也就没有支持。
  • 上述示例中使用的 JDBC 驱动是我们自己开发的版本(详见 https://github.com/DA1Y1/nebula-jdbc),与社区版的主要区别在 URL 上服务地址的指定以及⼀些转义字符的处理,后续也希望能将这些 Feature 合并到社区版本中,统⼀使⽤。

为了方便使用我们还开发了类似 mybatis-generator 这种工具来生成一些基础代码,提供基本的增删改查功能。感兴趣的同学可以在 IDEA 的 Plugins 中搜索 Nebula Generator 下载,使用方式参见:https://plugins.jetbrains.com/plugin/18026-nebula-generator

最后感谢 @DA1Y1 以及其他几位小伙伴的贡献!


交流图数据库技术?加入 Nebula 交流群请先填写下你的 Nebula 名片,Nebula 小助手会拉你进群~~

使用 MyBatis 操作 Nebula Graph 的实践的更多相关文章

  1. Neo4j 导入 Nebula Graph 的实践总结

    摘要: 主要介绍如何通过官方 ETL 工具 Exchange 将业务线上数据从 Neo4j 直接导入到 Nebula Graph 以及在导入过程中遇到的问题和优化方法. 本文首发于 Nebula 论坛 ...

  2. 分布式图数据库 Nebula Graph 的 Index 实践

    导读 索引是数据库系统中不可或缺的一个功能,数据库索引好比是书的目录,能加快数据库的查询速度,其实质是数据库管理系统中一个排序的数据结构.不同的数据库系统有不同的排序结构,目前常见的索引实现类型如 B ...

  3. Nebula Graph 在微众银行数据治理业务的实践

    本文为微众银行大数据平台:周可在 nMeetup 深圳场的演讲这里文字稿,演讲视频参见:B站 自我介绍下,我是微众银行大数据平台的工程师:周可,今天给大家分享一下 Nebula Graph 在微众银行 ...

  4. Nebula Graph 的 Ansible 实践

    本文首发于 Nebula Graph 公众号 NebulaGraphCommunity,Follow & 看大厂图数据库技术实践 背景 在 Nebula-Graph 的日常测试中,我们会经常在 ...

  5. Nebula Graph 在网易游戏业务中的实践

    本文首发于 Nebula Graph Community 公众号 当游戏上知识图谱,网易游戏是如何应对大规模图数据的管理问题,Nebula Graph 又是如何帮助网易游戏落地游戏内复杂的图的业务呢? ...

  6. GraphX 在图数据库 Nebula Graph 的图计算实践

    不同来源的异构数据间存在着千丝万缕的关联,这种数据之间隐藏的关联关系和网络结构特性对于数据分析至关重要,图计算就是以图作为数据模型来表达问题并予以解决的过程. 一.背景 随着网络信息技术的飞速发展,数 ...

  7. 解析 Nebula Graph 子图设计及实践

    本文首发于 Nebula Graph 公众号 NebulaGraphCommunity,Follow 看大厂图数据库技术实践. 前言 在先前的 Query Engine 源码解析中,我们介绍了 2.0 ...

  8. 分布式图数据库 Nebula Graph 中的集群快照实践

    1 概述 1.1 需求背景 图数据库 Nebula Graph 在生产环境中将拥有庞大的数据量和高频率的业务处理,在实际的运行中将不可避免的发生人为的.硬件或业务处理错误的问题,某些严重错误将导致集群 ...

  9. Nebula Graph 技术总监陈恒:图数据库怎么和深度学习框架进行结合?

    引子 Nebula Graph 的技术总监在 09.24 - 09.30 期间同开源中国·高手问答的小伙伴们以「图数据库的设计和实践」为切入点展开讨论,包括:「图数据库的存储设计」.「图数据库的计算设 ...

  10. 图数据库 Nebula Graph 的安装部署

    Nebula Graph:一个开源的分布式图数据库.作为唯一能够存储万亿个带属性的节点和边的在线图数据库,Nebula Graph 不仅能够在高并发场景下满足毫秒级的低时延查询要求,还能够实现服务高可 ...

随机推荐

  1. 一文带你搞懂如何优化慢SQL

    作者:京东科技 宋慧超 一.前言 最近通过SGM监控发现有两个SQL的执行时间占该任务总执行时间的90%,通过对该SQL进行分析和优化的过程中,又重新对SQL语句的执行顺序和SQL语句的执行计划进行了 ...

  2. vue获取子组件的实例$el、$attrs和inheritAttrs的使用

    我的需求 有些时候,我们需要获取组件的DOM元素 有些小伙伴会说,这还不简单 直接使用this.$ref.xx不就可以了吗 我们来看一下,是不是我们想的那样简单 组件内容 <template&g ...

  3. package.json中^,~的详细说明

    场景描述 在package.json这个文件中,我们经常可以看见这样的信息 但是我们很少注意的是 版本前面的 ^ 到底是什么意思 今天我们就来讲一下(端好小板凳) "dependencies ...

  4. 【验证码逆向专栏】数美验证码全家桶逆向分析以及 AST 获取动态参数

    声明 本文章中所有内容仅供学习交流使用,不用于其他任何目的,不提供完整代码,抓包内容.敏感网址.数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关! 本文章未经许 ...

  5. 在Protocol Buffers中导入当前目录中的.proto文件

    在protobuf中导入当前目录中的.proto文件时,可以使用相对路径.相对路径是相对于当前.proto文件所在的目录来引用其他.proto文件. 假设有以下目录结构: my_project/ |- ...

  6. 来啦!2020 Java开源项目权威排名解读:Spring Boot排名稳定、Shiro未上榜

    这篇文章对于我们做技术选型以及技术学习都有极强的指导性作用,建议收藏! 原创不易,若有帮助,欢迎点赞! 推荐: 接近100K star 的Java学习/面试指南 Github 95k+点赞的Java面 ...

  7. 《Mybatis 手撸专栏》第2章:创建简单的映射器代理工厂

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 着急和快,是最大的障碍! 慢下来,慢下来,只有慢下来,你才能看到更全的信息,才能学到 ...

  8. centos编译安装tcpdump

    环境 CentOS Linux release 7.9.2009 (Core) 准备安装包 libpcap-1.5.3.tar.gz tcpdump-4.9.2.tar.gz 下载地址:https:/ ...

  9. Linux系统NTP校时的微调模式

    前言: Linux系统有两个时间同步服务:ntpd和chrony,一般较低版本的系统使用ntpd,新版本系统使用chrony. ntpd有两种校时策略slew和step: slew是平滑.缓慢的渐进式 ...

  10. 编译Assimp时出现“warning C4819”的解决方案

      最近又重新捣鼓起了OpenGL, 使用Assimp库加载3D模型,最新(2023/12/9)的版本是5.3.1. 使用cmake编译本是一件简单的事情: cmake . cmake --build ...