{"id":25569605,"url":"https://github.com/nebula-contrib/ngbatis","last_synced_at":"2025-06-14T11:40:50.926Z","repository":{"id":37967786,"uuid":"502199631","full_name":"nebula-contrib/ngbatis","owner":"nebula-contrib","description":"NGBATIS is a database ORM framework base NebulaGraph + spring-boot, which takes advantage of the mybatis’ fashion development, including some de-factor operations in single table and vertex-edge, like mybatis-plus. NGBATIS 是一款针对 NebulaGraph + Springboot 的数据库 ORM 框架。借鉴于 MyBatis 的使用习惯进行开发。https://graph-cn.github.io/ngbatis-docs/","archived":false,"fork":false,"pushed_at":"2025-06-06T10:49:35.000Z","size":1182,"stargazers_count":145,"open_issues_count":72,"forks_count":45,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-06-06T11:28:11.737Z","etag":null,"topics":["asm","graph-database","hacktoberfest","java","mybatis","nebula","nebula-graph","nebulagraph","orm","springboot"],"latest_commit_sha":null,"homepage":"https://nebula-contrib.github.io/ngbatis/","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nebula-contrib.png","metadata":{"files":{"readme":"README-CN.md","changelog":"CHANGELOG-CN.md","contributing":"CONTRIBUTING-CN.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2022-06-10T22:50:00.000Z","updated_at":"2025-06-06T10:36:52.000Z","dependencies_parsed_at":"2024-05-23T04:31:29.762Z","dependency_job_id":"f74f076c-828b-4ecb-9266-54a942aa7e59","html_url":"https://github.com/nebula-contrib/ngbatis","commit_stats":{"total_commits":201,"total_committers":13,"mean_commits":"15.461538461538462","dds":0.2885572139303483,"last_synced_commit":"237d4f53287b8537b54c9246bc1cac1e7f3f7652"},"previous_names":[],"tags_count":17,"template":false,"template_full_name":null,"purl":"pkg:github/nebula-contrib/ngbatis","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nebula-contrib%2Fngbatis","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nebula-contrib%2Fngbatis/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nebula-contrib%2Fngbatis/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nebula-contrib%2Fngbatis/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nebula-contrib","download_url":"https://codeload.github.com/nebula-contrib/ngbatis/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nebula-contrib%2Fngbatis/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":259810961,"owners_count":22915134,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["asm","graph-database","hacktoberfest","java","mybatis","nebula","nebula-graph","nebulagraph","orm","springboot"],"created_at":"2025-02-21T00:02:31.713Z","updated_at":"2025-06-14T11:40:50.918Z","avatar_url":"https://github.com/nebula-contrib.png","language":"Java","funding_links":[],"categories":["数据库开发"],"sub_categories":[],"readme":"\r\n\u003c!--\r\nCopyright (c) 2022 All project authors and nebula-contrib. All rights reserved.\r\n\r\nThis source code is licensed under Apache 2.0 License.\r\n--\u003e\r\n\r\n# NgBatis\r\n\r\n\u003cp align=\"center\"\u003e\r\n  \u003cbr\u003e \u003ca href=\"README.md\"\u003eEnglish\u003c/a\u003e | 中文\r\n\u003c/p\u003e\r\n\r\n- [NgBatis Docs](https://nebula-contrib.github.io/ngbatis/)\r\n- [NgBatis 文档](https://graph-cn.github.io/ngbatis-docs/)\r\n\r\n## NGBATIS是什么？\r\n\r\n**NgBatis** 是一款针对 [Nebula Graph](https://github.com/vesoft-inc/nebula) + Springboot 的数据库 ORM 框架。借鉴于 [MyBatis](https://github.com/mybatis/mybatis-3) 的使用习惯进行开发。包含了一些类似于[mybatis-plus](https://github.com/baomidou/mybatis-plus)的单表操作，另外还有一些图特有的实体-关系基本操作。  \r\n如果使用上更习惯于JPA的方式，[graph-ocean](https://github.com/nebula-contrib/graph-ocean) 是个不错的选择。\r\n\r\n## NgBatis 是怎么运行的？\r\n\r\n请看设计文档 [EXECUTION-PROCESS.md](./EXECUTION-PROCESS.md)\r\n\r\n## 项目要求\r\n\r\n- Springboot\r\n- Maven\r\n- Java 8+\r\n\r\n## 版本匹配\r\n\r\n  NgBatis | nebula-java | JDK | Springboot | Beetl\r\n  ---|-------------|---|------------|---\r\n  2.0.1 | 3.8.3       | 8 | 2.7.0 | 3.15.10.RELEASE\r\n  2.0.0-beta | 3.8.3       | 8 | 2.7.0 | 3.15.10.RELEASE\r\n  1.3.0 | 3.8.3       | 8 | 2.7.0 | 3.15.10.RELEASE\r\n  1.3.0-jdk17 | 3.8.3       | 17 | 3.0.7 | 3.15.10.RELEASE\r\n  1.2.2 | 3.6.0       | 8 | 2.7.0 | 3.15.10.RELEASE\r\n  1.2.2-jdk17 | 3.6.0       | 17 | 3.0.7 | 3.15.10.RELEASE\r\n  1.2.1 | 3.6.0       | 8 | 2.7.0 | 3.15.10.RELEASE\r\n  1.2.0-jdk17 | 3.6.0       | 17 | 3.0.7 | 3.15.10.RELEASE\r\n  1.2.0 | 3.6.0       | 8 | 2.7.0 | 3.15.10.RELEASE\r\n  1.1.5 | 3.5.0       | 8 | 2.7.0 | 3.1.8.RELEASE\r\n  1.1.4 | 3.5.0       | 8 | 2.7.0 | 3.1.8.RELEASE\r\n  1.1.3 | 3.5.0       | 8 | 2.7.0 | 3.1.8.RELEASE\r\n  1.1.2 | 3.4.0       | 8 | 2.7.0 | 3.1.8.RELEASE\r\n\r\n### 快照版\r\n\r\n  NgBatis | nebula-java | JDK | Springboot | Beetl\r\n  ---|-------------|---|------------|---\r\n  1.2.2-jdk17-SNAPSHOT | 3.6.0       | 17 | 3.0.7 | 3.15.10.RELEASE\r\n  1.2.2-SNAPSHOT | 3.6.0       | 8 | 2.7.0 | 3.15.10.RELEASE\r\n\r\n\u003e 在同版本号快照版中，依赖的第三方可能会随时升级\r\n\r\n## 如何使用（可在克隆代码后，参考 ngbatis-demo 项目）\r\n\r\n### 在项目引入\r\n\r\n- Maven\r\n\r\n    ```xml\r\n        \u003cdependency\u003e\r\n          \u003cgroupId\u003eorg.nebula-contrib\u003c/groupId\u003e\r\n          \u003cartifactId\u003engbatis\u003c/artifactId\u003e\r\n          \u003cversion\u003e1.3.0\u003c/version\u003e\r\n        \u003c/dependency\u003e\r\n    ```\r\n\r\n- Gradle\r\n\r\n    ```groovy\r\n    implementation 'org.nebula-contrib:ngbatis:1.3.0'\r\n    ```\r\n\r\n### 参考 [【ngbatis-demo】](./ngbatis-demo)，与springboot无缝集成。在该项目的 test 中还有api的样例。在开发过程中每增加一个特性也都会同步更新ngbatis-demo的用例\r\n\r\n### 配置数据库\r\n\r\n在 application.yml 中添加配置 **将数据源修改成可访问到的NebulaGraph**\r\n\r\n```yml\r\nnebula:\r\n  ngbatis:\r\n    session-life-length: 300000 # since v1.1.2\r\n    check-fixed-rate: 300000 # since v1.1.2\r\n    # `use-session-pool` 默认是 false，如开启，则 space 是必须指定的\r\n    # space除了使用当前文件的声明意外，还可以使用：(@Space) or xml(space=\"test\")\r\n    use-session-pool: false # since v1.1.2\r\n  hosts: 127.0.0.1:19669, 127.0.0.1:9669\r\n  username: root\r\n  password: nebula\r\n  space: test\r\n  pool-config:\r\n    min-conns-size: 0\r\n    max-conns-size: 10\r\n    timeout: 0\r\n    idle-time: 0\r\n    interval-idle: -1\r\n    wait-time: 0\r\n    min-cluster-health-rate: 1.0\r\n    enable-ssl: false\r\n```\r\n\r\n### 扫描动态代理的 bean\r\n\r\n```java\r\n@SpringBootApplication(scanBasePackages = { \"org.nebula\", \"your.domain\"})\r\npublic class YourApplication {\r\n    public static void main(String[] args) {\r\n        new SpringApplication(YourApplication.class).run(args);\r\n    }\r\n}\r\n```\r\n\r\n\u003e 如果项目中使用的是 SpringCloud，\r\n\u003e 请使用`@ComponentScan( basePackages = {\"org.nebula.contrib\", \"your.domain\"} )`\r\n\r\n## 日常开发示例\r\n\r\n### 自己编写 nGQL (MyBatis的思路)\r\n\r\n#### 声明数据访问接口\r\n\r\n```java\r\npackage ye.weicheng.ngbatis.demo.repository;\r\n\r\nimport ye.weicheng.ngbatis.demo.pojo.Person;\r\nimport java.util.List;\r\nimport java.util.Map;\r\nimport java.util.Set;\r\n\r\npublic interface TestRepository {\r\n    // new features from v1.2.0\r\n    Integer returnAge(@Param(\"person\")Person person);\r\n  \r\n    Person selectPerson();\r\n    Person selectByPerson(Person person);\r\n    List\u003cPerson\u003e selectAgeGt(Integer age);\r\n    List\u003cString\u003e selectListString();\r\n    List\u003cMap\u003e selectPersonsMap();\r\n    Map\u003cString, Object\u003e selectTriple();\r\n}\r\n\r\n```\r\n\r\n#### 编写数据访问语句\r\n\r\nresource/mapper/TestRepository.xml\r\n\r\n```xml\r\n\u003cmapper\r\n    namespace=\r\n    \"ye.weicheng.ngbatis.demo.repository.TestRepository\"\r\n\u003e\r\n    \u003c!-- v1.2.0 新特性 start --\u003e\r\n    \u003cnGQL id=\"include-test-value\"\u003e\r\n        ${myInt}\r\n    \u003c/nGQL\u003e\r\n\r\n    \u003cnGQL id=\"ngql-return-age\"\u003e\r\n        RETURN @ng.include('include-test-value',{'myInt':age});\r\n    \u003c/nGQL\u003e\r\n\r\n    \u003c!--\r\n    等同于: \r\n        RETURN ${person.age};\r\n    你可以试着提取更多有意义的公共脚本.\r\n    --\u003e\r\n    \u003cselect id=\"returnAge\" resultType=\"java.lang.Integer\"\u003e\r\n        @ng.include('ngql-return-age',person);\r\n    \u003c/select\u003e\r\n    \u003c!-- v1.2.0 新特性 v1.2.0 end --\u003e\r\n\r\n    \u003cselect id=\"selectPerson\" resultType=\"ye.weicheng.ngbatis.demo.pojo.Person\"\u003e\r\n        match (v:person) return v.person.name as name, v.person.age as age limit 1\r\n    \u003c/select\u003e\r\n\r\n    \u003cselect id=\"selectAgeGt\" resultType=\"ye.weicheng.ngbatis.demo.pojo.Person\"\u003e\r\n        MATCH (n: person)\r\n        WHERE n.person.age \u003e $p0\r\n        RETURN n\r\n        LIMIT 100\r\n    \u003c/select\u003e\r\n\r\n\r\n    \u003cselect id=\"selectByPerson\" resultType=\"ye.weicheng.ngbatis.demo.pojo.Person\"\u003e\r\n        MATCH (n: person)\r\n        WHERE n.person.name == $p0.name\r\n        RETURN n\r\n        LIMIT 100\r\n    \u003c/select\u003e\r\n\r\n    \u003cselect id=\"selectListString\" resultType=\"java.lang.String\"\u003e\r\n        match (v:person) return v.person.name as name limit 100\r\n    \u003c/select\u003e\r\n\r\n    \u003cselect id=\"selectPersonsMap\" resultType=\"java.util.Map\"\u003e\r\n        match (v:person) return v.person.name as name, v.person.age  as age limit 100\r\n    \u003c/select\u003e\r\n\r\n    \u003cselect id=\"selectTriple\" resultType=\"java.util.Map\"\u003e\r\n        MATCH (n: person)-[r: like]-\u003e(n2: person)\r\n        RETURN n, r, n2\r\n        LIMIT 100\r\n    \u003c/select\u003e\r\n\r\n    \u003c!-- \r\n        更多复杂的 nGQL 可能还需要充分的测试，\r\n        目前我自己在用的项目两层对象的数据结构也是可以满足的。\r\n        Path 因为开发中基本都可以用 n, r, n2 的结构处理，便还没来得及支持。\r\n    --\u003e\r\n\r\n\u003c/mapper\u003e\r\n```\r\n\r\n### 使用基类自带的 nGQL 实现图的基本操作（MyBatis-plus）的思路\r\n\r\n#### model-vertex\r\n\r\n```java\r\npackage com.example.model.vertex.Person;\r\n\r\nimport lombok.Data;\r\nimport javax.persistence.Id;\r\nimport javax.persistence.Table;\r\n\r\n@Data\r\n@Table(name = \"person\")\r\npublic class Person {\r\n    @Id\r\n    private String name;\r\n    private Integer age;\r\n}\r\n```\r\n\r\n#### model-edge\r\n\r\n```java\r\npackage com.example.model.edge.Like;\r\n\r\nimport lombok.AllArgsConstructor;\r\nimport lombok.NoArgsConstructor;\r\nimport lombok.Data;\r\nimport javax.persistence.Table;\r\n\r\n@Data\r\n@Table(name = \"like\")\r\n@NoArgsConstructor\r\n@AllArgsConstructor\r\npublic class Like {\r\n    private Double likeness;\r\n}\r\n```\r\n\r\n#### dao\r\n\r\n```java\r\npackage com.example.dao;\r\n\r\nimport org.nebula.contrib.ngbatis.proxy.NebulaDaoBasic;\r\nimport com.example.model.vertex.Person;\r\n\r\npublic interface PersonDao extends NebulaDaoBasic\u003cPerson, String\u003e{}\r\n```\r\n\r\n#### xml（不可缺少）\r\n\r\n```xml\r\n\u003cmapper\r\n    namespace=\r\n    \"com.example.dao.PersonDao\"\r\n\u003e\r\n\u003c/mapper\u003e\r\n```\r\n\r\n#### service\r\n\r\n```java\r\npackage com.example.service;\r\n\r\nimport org.nebula.contrib.ngbatis.utils.Page;\r\nimport com.example.dao.PersonDao;\r\nimport com.example.model.vertex.Person;\r\nimport com.example.model.edge.Like;\r\n\r\n@Service\r\npublic class PersonServiceImpl {\r\n\r\n    @Autowired private PersonDao dao;\r\n\r\n    public void demos() {\r\n        // 实现 两个节点插入\r\n        Person tom = new Person();\r\n        tom.setName(\"Tom\");\r\n        dao.insert( tom ); \r\n        \r\n        Person jerry = new Person();\r\n        jerry.setName( \"Jerry\" );\r\n        dao.insert( jerry );\r\n\r\n        // 建立两个节点的关系\r\n        Like like = new Like( 0.99999 );\r\n        dao.insertEdge( tom, like, jerry );\r\n\r\n        // 查找喜欢 jerry 的人\r\n        String jerryId = jerry.getName();\r\n        List\u003cPerson\u003e whoLikeJerry = dao.listStartNodes( Like.class, jerryId );\r\n\r\n        // 查找唯一喜欢 jerry 的人。非唯一时报错。（限定在特定关系仅有一个上游的场景）\r\n        Person tom = dao.startNode( Like.class, jerryId );\r\n\r\n        // 查看 Tom 跟 Jerry 之间的 Like关系\r\n        String tomId = tom.getName();\r\n        Boolean tomLikeJerry = dao.existsEdge( tomId, Like.class, jerryId ); // true\r\n        Boolean jerryLikeTom = dao.existsEdge( jerryId, Like.class, tomId ); // false\r\n        // 可怜的 Tom\r\n\r\n        // 根据 Tom 的名字查找全部信息\r\n        Person tomDb = dao.selectById( \"Tom\" );\r\n\r\n        // 查找分页\r\n        Page\u003cPerson\u003e page = new Page\u003c\u003e();\r\n        List\u003cPerson\u003e personPage = dao.selectPage( page );\r\n        page.getTotal(); // 2 rows， Tom and Jerry\r\n        Boolean theyAreFamily = page.getRows() == personPage; // true\r\n\r\n        // 故事总想要有个好的结局\r\n        dao.insertEdge( jerry, like, tom );\r\n\r\n        // 更多 基类的操作还在开发中。期待\r\n    }\r\n\r\n\r\n}\r\n\r\n```\r\n\r\n### 使用提供的方法进行实体直查（OGM）\r\n\r\n该查询方式是从实体对象出发完成数据直查。使用前要定义实体类，作为查询参数。\r\n\r\n#### 实体类\r\n\r\n##### 点实体\r\n\r\n- 继承`GraphBaseVertex`类标识是点实体\r\n- `@Tag`的name属性注明点实体的Tag\r\n\r\n```java\r\n@Tag(name = \"player\")\r\npublic class Player extends GraphBaseVertex {\r\n\r\n  @Id\r\n  private String id;\r\n\r\n  private String name;\r\n\r\n  private Integer age;\r\n    \r\n  ...\r\n\r\n}\r\n```\r\n\r\n具体可参考`ye.weicheng.ngbatis.demo.pojo.edge`包下的点实体示例。\r\n\r\n##### 边实体\r\n\r\n- 继承`GraphBaseEdge`类标识是边实体\r\n- `@EdgeType`的name属性注明边实体的类型\r\n- `@Id`（可选，如果两个节点之间同一类型边的唯一性由源节点id和目标节点id共同决定，可以不加当前属性）\r\n- `@SrcId`（可选，如果不需要获取关系的源节点id，可以不加当前属性）\r\n- `@DstId`（可选，如果不需要获取关系的目标节点id，可以不加当前属性）\r\n\r\n```java\r\n@EdgeType(name = \"serve\")\r\npublic class Serve extends GraphBaseEdge {\r\n\r\n  @Id \r\n  private Long rank;\r\n\r\n  @SrcId \r\n  private String srcId;\r\n\r\n  @DstId \r\n  private String dstId;\r\n\r\n  @Column(name = \"start_year\")\r\n  private Integer startYear;\r\n  @Column(name = \"end_year\")\r\n  private Integer endYear;\r\n\r\n  ...\r\n}\r\n```\r\n\r\n具体可参考`ye.weicheng.ngbatis.demo.pojo.vertex`包下的边实体示例。\r\n\r\n#### 现提供的方法\r\n\r\n##### 关于点实体\r\n\r\nAPI | 用法说明\r\n--|--\r\nqueryIdsByProperties()                           | 查询特定Tag或者属性的点Id集合\r\nqueryVertexById()                                | 查询特定点Id的单个点\r\nqueryVertexByTag()                               | 查询特定Tag的点集合\r\nqueryVertexByProperties()                        | 查询特定属性的点集合\r\nqueryAllAdjacentVertex(Class\u003c?\u003e... edgeClass)    | 查询特定点的所有邻点集合，可指定一个或多个连接两点的边类型\r\nqueryIncomingAdjacentVertex(Class\u003c?\u003e... edgeClass) | 查询特定点入边方向的邻点集合，可指定一个或多个连接两点的边类型\r\nqueryOutgoingAdjacentVertex(Class\u003c?\u003e... edgeClass) | 查询特定点出边方向的邻点集合，可指定一个或多个连接两点的边类型\r\nqueryNeighborIdsWithHopById(int m, int n, Class\u003c?\u003e... edgeClass) | 查询特定点指定跳数内的点Id集合，可指定一个或多个连接两点的边类型\r\nqueryConnectedEdgesById(Direction direction)     | 查询特定点关联的所有边集合，可指定边的方向和类型\r\nqueryPathFromVertex(Direction direction)         | 查询特定点关联的所有路径集合，可指定边的方向\r\nqueryFixedLengthPathFromVertex(Integer maxHop, Direction direction, Class\u003c?\u003e... edgeClass) | 查询特定点出发的定长路径集合，可指定最大步数、边的方向、边的类型\r\nqueryVariableLengthPathFromVertex(Integer minHop, Integer maxHop,   Direction direction, Class\u003c?\u003e... edgeClass) | 查询特定点出发的变长路径集合，可指定最小步数、最大步数、边的方向、边的类型\r\nqueryShortestPathFromSrcAndDst(Integer maxHop,   Direction direction, T v2) | 查询特定点出发的任意一条最短路径，可指定步数、边的方向、终点实体\r\nqueryAllShortestPathsFromSrcAndDst(Integer maxHop,   Direction direction, T v2) | 查询从该点出发的所有最短路径集合，可指定步数、边的方向、终点实体\r\nqueryVertexCountByTag()                          | 查询特定Tag的点的数量\r\n\r\n具体实现见`org.nebula.contrib.ngbatis.base`包下的点实体基类`GraphBaseVertex`。\r\n\r\n##### 关于边实体\r\n\r\nAPI | 用法说明\r\n--|--\r\nqueryEdgeByType(Direction direction)             | 查询特定类型、方向的边集合\r\nqueryEdgeWithSrcAndDstByProperties(T srcVertex, Direction direction, T dstVertex) | 查询特定属性的边集合\r\nqueryEdgePropertiesBySrcAndDstId()               | 查询特定始终点id的边集合\r\nqueryEdgeCountByType()                           | 查询特定Type的边的数量\r\n\r\n具体实现见`org.nebula.contrib.ngbatis.base`包下的边实体基类`GraphBaseEdge`。\r\n\r\n#### 使用示例\r\n\r\n```java\r\n@Test\r\npublic void testVertex(){\r\n    Player srcPlayer = new Player();\r\n    //查询所有符合条件 name = \"Vince Carter\" 的Player顶点\r\n    srcPlayer.setName(\"Vince Carter\");\r\n    List\u003cPlayer\u003e vertices = player.queryVertexByProperties();\r\n}\r\n\r\n@Test\r\npublic void testEdge(){\r\n    Serve serve = new Serve();\r\n    \r\n    //查询起点id为player100，终点id为team204的Serve边\r\n    serve.setSrcId(\"player100\");\r\n    serve.setDstId(\"team204\");\r\n    Serve edge = serve.queryEdgeWithSrcAndDstByProperties();\r\n    \r\n    //查询Serve类型、方向为”-\u003e“的边\r\n    List\u003cServe\u003e edges = serve.queryEdgeByType(Direction.NULL);\r\n    \r\n}\r\n```\r\n\r\n具体每个直查方法的使用示例可参考ngbatis-demo里的NebulaGraphBasicTests测试类。\r\n\r\n## 特别声明的上游项目\r\n\r\n- [beetl](https://gitee.com/xiandafu/beetl), BSD-3, Beetl模板引擎是项目很重要的组成部分(as is).\r\n\r\n## 开源协议\r\n\r\n项目遵循 [Apache License, Version 2.0, January 2004](https://www.apache.org/licenses/LICENSE-2.0) 开源协议。\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnebula-contrib%2Fngbatis","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnebula-contrib%2Fngbatis","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnebula-contrib%2Fngbatis/lists"}