本文首发于 NebulaGraph 公众号 https://mp.weixin.qq.com/s/z56o6AEz1Z4RmS8Zdx6dTA
大家好,我是开源我的项目 NGbatis 的发起人大叶(CorvusYe@GitHub)。目前 NGbatis 也已成为 NebulaGraph 开源生态我的项目之一。在过来的 4 个月里,NGbatis 从提交第一行代码以来,曾经公布了 3 个版本,正在一步步变得越来越好。感激一路同行的人们。
这里给大家贴上仓库地址:https://github.com/nebula-contrib/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 为例,即:
依据最奢侈的 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'
六、全局流程图
七、NGbatis 该如何集成到本人的 Springboot 我的项目
- 增加依赖
<dependency>
<groupId>org.nebula-contrib</groupId>
<artifactId>ngbatis</artifactId>
<version>1.1.0-rc</version>
</dependency>
- 配置 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
- 增加扫描包以引入 NGbatis bean
@SpringBootApplication(exclude={ DataSourceAutoConfiguration.class},
scanBasePackages = {"org.nebula.contrib", "your.domain"} )
public class YourSpringbootApplication {}
- 申明主键生成器
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;
}
}
到此,对于集成工作来说,工作曾经实现,剩下就是开发的工作了。
开发人员只须要做三件事:
- 定义接口:
package your.domain;
import org.nebula.contrib.ngbatis.proxy.NebulaDaoBasic;
public interface PersonDao extends NebulaDaoBasic<Person, String> {Person selectByName( @Param("name") String param );
}
- 在 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>
-
调用
-
注入:
@Autowired private PersonDao dao;
-
调用自定义接口
Person tom = dao.selectByName("Tom");
更多文档:自定义 nGQL
-
调用基类接口
// 不论属性是否为空,如果数据库中已有对应 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 用户一起交换图数据库技术和利用技能,留下「你的名片」一起游玩呢~