From fb6eafb24d8898cb67c859e6205ee34bfe093dfb Mon Sep 17 00:00:00 2001
From: charle004 <937002632@qq.com>
Date: Thu, 5 Sep 2024 10:47:51 +0800
Subject: [PATCH 1/6] support multiple mapper-locations
---
.../contrib/ngbatis/NgbatisContextInitializer.java | 2 +-
.../nebula/contrib/ngbatis/config/ParseCfgProps.java | 8 ++++----
.../contrib/ngbatis/io/MapperResourceLoader.java | 10 ++++++----
3 files changed, 11 insertions(+), 9 deletions(-)
diff --git a/src/main/java/org/nebula/contrib/ngbatis/NgbatisContextInitializer.java b/src/main/java/org/nebula/contrib/ngbatis/NgbatisContextInitializer.java
index 51f3653..1e124ee 100644
--- a/src/main/java/org/nebula/contrib/ngbatis/NgbatisContextInitializer.java
+++ b/src/main/java/org/nebula/contrib/ngbatis/NgbatisContextInitializer.java
@@ -62,7 +62,7 @@ private ParseCfgProps readParseCfgProps(ConfigurableEnvironment environment) {
.setLogShow(environment.getProperty("cql.parser.log-show"))
.setMapper(environment.getProperty("cql.parser.mapper"))
.setNamespace(environment.getProperty("cql.parser.namespace"))
- .setMapperLocations(environment.getProperty("cql.parser.mapper-locations"))
+ .setMapperLocations(environment.getProperty("cql.parser.mapper-locations", String[].class))
.setMapperTplLocation(environment.getProperty("cql.parser.mapper-tpl-location"))
.setResultType(environment.getProperty("cql.parser.result-type"))
.setParameterType(environment.getProperty("cql.parser.parameter-type"))
diff --git a/src/main/java/org/nebula/contrib/ngbatis/config/ParseCfgProps.java b/src/main/java/org/nebula/contrib/ngbatis/config/ParseCfgProps.java
index 89f700a..2b94c76 100644
--- a/src/main/java/org/nebula/contrib/ngbatis/config/ParseCfgProps.java
+++ b/src/main/java/org/nebula/contrib/ngbatis/config/ParseCfgProps.java
@@ -25,7 +25,7 @@ public class ParseCfgProps {
private String mapperTplLocation = "NebulaDaoBasic.xml";
- private String mapperLocations = "mapper/**/*.xml";
+ private String[] mapperLocations = {"mapper/**/*.xml"};
private String id = "id";
@@ -75,7 +75,7 @@ public ParseCfgProps setMapperTplLocation(String mapperTplLocation) {
*
获取开发者业务dao对应xml所存放的路径。
* @return 开发者业务dao对应xml所存放的路径
*/
- public String getMapperLocations() {
+ public String[] getMapperLocations() {
return mapperLocations;
}
@@ -84,8 +84,8 @@ public String getMapperLocations() {
* @param mapperLocations 业务dao对应xml所存放的路径
* @return 解析配置(本应是 void,为支持链式调用而改)
*/
- public ParseCfgProps setMapperLocations(String mapperLocations) {
- if (isBlank(mapperLocations)) {
+ public ParseCfgProps setMapperLocations(String[] mapperLocations) {
+ if (isEmpty(mapperLocations)) {
return this;
}
this.mapperLocations = mapperLocations;
diff --git a/src/main/java/org/nebula/contrib/ngbatis/io/MapperResourceLoader.java b/src/main/java/org/nebula/contrib/ngbatis/io/MapperResourceLoader.java
index ce7e196..7c534d9 100644
--- a/src/main/java/org/nebula/contrib/ngbatis/io/MapperResourceLoader.java
+++ b/src/main/java/org/nebula/contrib/ngbatis/io/MapperResourceLoader.java
@@ -87,11 +87,13 @@ public MapperResourceLoader(ParseCfgProps parseConfig,ApplicationContext applica
@TimeLog(name = "xml-load", explain = "mappers xml load completed : {} ms")
public Map load() {
Map resultClassModel = new HashMap<>();
- String mapperLocations = parseConfig.getMapperLocations();
+ String[] mapperLocations = parseConfig.getMapperLocations();
try {
- Resource[] resources = getResources(mapperLocations);
- for (Resource resource : resources) {
- resultClassModel.putAll(parseClassModel(resource));
+ for (String mapperLocation : mapperLocations) {
+ Resource[] resources = getResources(mapperLocation);
+ for (Resource resource : resources) {
+ resultClassModel.putAll(parseClassModel(resource));
+ }
}
} catch (FileNotFoundException ffe) {
log.warn("No mapper files were found in path pattern '{}', please add", mapperLocations);
From 6ab32487f8209f0c6d12f84312e144c6eb79197d Mon Sep 17 00:00:00 2001
From: charle004 <937002632@qq.com>
Date: Mon, 9 Sep 2024 16:27:54 +0800
Subject: [PATCH 2/6] space config in mapper xml supports dynamic configuration
---
CHANGELOG.md | 15 +++++++++++----
.../contrib/ngbatis/io/MapperResourceLoader.java | 12 ++++++++++++
2 files changed, 23 insertions(+), 4 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index c1b24d2..cb5bc11 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -78,9 +78,9 @@ This source code is licensed under Apache 2.0 License.
Route-Tag: abc
```
-- feat: @Space annotation supports dynamic configuration.
- > @Space 注解的 name 属性值可通过 spring 配置文件自定义配置。
- - example:
+- feat: @Space annotation and space config in mapper xml supports dynamic configuration.
+ > @Space 注解的 name 属性值和 xml 文件中 Mapper 标签指定的 Space 可通过 spring 配置文件自定义配置。
+ - @Space example:
```yaml
app:
@@ -89,7 +89,7 @@ This source code is licensed under Apache 2.0 License.
```
```java
- @Space(name = "${nebula.space}")
+ @Space(name = "${app.person.space}")
@Table(name = "person")
public class Person {
@Id
@@ -113,7 +113,14 @@ This source code is licensed under Apache 2.0 License.
}
}
```
+
+ - XML example:
+ ```xml
+
+
+ ```
+
# 1.2.2
## Bugfix
diff --git a/src/main/java/org/nebula/contrib/ngbatis/io/MapperResourceLoader.java b/src/main/java/org/nebula/contrib/ngbatis/io/MapperResourceLoader.java
index 7c534d9..661ee92 100644
--- a/src/main/java/org/nebula/contrib/ngbatis/io/MapperResourceLoader.java
+++ b/src/main/java/org/nebula/contrib/ngbatis/io/MapperResourceLoader.java
@@ -127,6 +127,9 @@ public Map parseClassModel(Resource resource)
// 从注解获取 space
if (null == cm.getSpace()) {
setClassModelBySpaceAnnotation(cm);
+ }else {
+ //动态解析 XML 中 mapper 标签配置的 Space 属性
+ setClassModelByXmlConfigSpace(cm);
}
addSpaceToSessionPool(cm.getSpace());
@@ -140,6 +143,15 @@ public Map parseClassModel(Resource resource)
return result;
}
+ /**
+ * 解析自定义的 XML 中的 mapper 标签设置的 space
+ * @param cm ClassModel
+ */
+ private void setClassModelByXmlConfigSpace(ClassModel cm) {
+ String space = tryResolvePlaceholder(cm.getSpace());
+ cm.setSpace(space);
+ }
+
/**
* 设置 space
* @param cm ClassModel
From 4e4a1f84ee6a06500778c880fb80e2d2ac165567 Mon Sep 17 00:00:00 2001
From: charle004 <937002632@qq.com>
Date: Mon, 9 Sep 2024 16:39:26 +0800
Subject: [PATCH 3/6] changelog style
---
pom.xml | 25 +++++++------------------
1 file changed, 7 insertions(+), 18 deletions(-)
diff --git a/pom.xml b/pom.xml
index 68af988..734951b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -13,7 +13,7 @@
ngbatis
org.nebula-contrib
ngbatis
- 1.3.0
+ 1.3.0-snapshot
NgBatis is a database ORM framework base NebulaGraph + spring-boot,
@@ -157,17 +157,6 @@
-
- org.sonatype.plugins
- nexus-staging-maven-plugin
- 1.6.13
- true
-
- ossrh
- https://s01.oss.sonatype.org
- true
-
-
@@ -396,14 +385,14 @@
- ossrh
- Nexus Release Repository
- https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/
+ nexus-releases
+ http://172.17.10.100:8081/nexus/content/repositories/releases
- ossrh
- Nexus Snapshot Repository
- https://s01.oss.sonatype.org/content/repositories/snapshots
+ nexus-snapshots
+ http://172.17.10.100:8081/nexus/content/repositories/snapshots
+
+
From ff9c93a25b4e076d6987d7b77adc45b6d2a1b2fb Mon Sep 17 00:00:00 2001
From: charle004 <937002632@qq.com>
Date: Mon, 9 Sep 2024 16:43:52 +0800
Subject: [PATCH 4/6] changelog style
---
CHANGELOG.md | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index cb5bc11..52c27b9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -87,7 +87,7 @@ This source code is licensed under Apache 2.0 License.
person:
space: PERSON_SPACE
```
-
+
```java
@Space(name = "${app.person.space}")
@Table(name = "person")
@@ -113,14 +113,16 @@ This source code is licensed under Apache 2.0 License.
}
}
```
-
+
- XML example:
+
```xml
```
-
+
+
# 1.2.2
## Bugfix
From 5f175903986d12a4e1b64976c21a03ffc3402f41 Mon Sep 17 00:00:00 2001
From: charle004 <937002632@qq.com>
Date: Mon, 9 Sep 2024 16:45:40 +0800
Subject: [PATCH 5/6] changelog style
---
CHANGELOG.md | 1 -
1 file changed, 1 deletion(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 52c27b9..4b91941 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -122,7 +122,6 @@ This source code is licensed under Apache 2.0 License.
```
-
# 1.2.2
## Bugfix
From 5f139f1d21bedc7cce405dc96344892d07220c05 Mon Sep 17 00:00:00 2001
From: CorvusYe
Date: Sat, 21 Dec 2024 21:03:05 +0800
Subject: [PATCH 6/6] (v2.0.0-beta)feat: Support switching graph space based on
parameters for multiple functions.
---
CHANGELOG-CN.md | 51 ++++
CHANGELOG.md | 52 +++-
README-CN.md | 3 +-
README.md | 8 +-
ngbatis-demo/pom.xml | 2 +-
.../weicheng/ngbatis/demo/pojo/Paragraph.java | 35 +++
.../ngbatis/demo/repository/ParagraphDao.java | 27 ++
.../src/main/resources/application.yml | 1 +
.../main/resources/mapper/ParagraphDao.xml | 20 ++
.../ngbatis/demo/NebulaGraphBasicTests.java | 6 +-
.../demo/repository/ParagraphDaoTest.java | 63 +++++
pom.xml | 23 +-
.../java/org/nebula/contrib/ngbatis/Env.java | 55 ----
.../NgbatisBeanFactoryPostProcessor.java | 17 +-
.../contrib/ngbatis/SessionDispatcher.java | 2 +
.../contrib/ngbatis/base/GraphBaseExt.java | 36 +--
.../ngbatis/io/MapperResourceLoader.java | 54 +---
.../contrib/ngbatis/models/MapperContext.java | 24 ++
.../contrib/ngbatis/proxy/MapperProxy.java | 167 ++++++------
.../IntervalCheckSessionDispatcher.java | 12 +-
.../contrib/ngbatis/session/SpaceRouter.java | 239 ++++++++++++++++++
.../contrib/ngbatis/utils/ReflectUtil.java | 55 ++--
22 files changed, 656 insertions(+), 296 deletions(-)
create mode 100644 CHANGELOG-CN.md
create mode 100644 ngbatis-demo/src/main/java/ye/weicheng/ngbatis/demo/pojo/Paragraph.java
create mode 100644 ngbatis-demo/src/main/java/ye/weicheng/ngbatis/demo/repository/ParagraphDao.java
create mode 100644 ngbatis-demo/src/main/resources/mapper/ParagraphDao.xml
create mode 100644 ngbatis-demo/src/test/java/ye/weicheng/ngbatis/demo/repository/ParagraphDaoTest.java
create mode 100644 src/main/java/org/nebula/contrib/ngbatis/session/SpaceRouter.java
diff --git a/CHANGELOG-CN.md b/CHANGELOG-CN.md
new file mode 100644
index 0000000..79f6559
--- /dev/null
+++ b/CHANGELOG-CN.md
@@ -0,0 +1,51 @@
+
+
+
+# 2.0.0-beta
+
+## Bug修复
+
+- fix: [#329](https://github.com/nebula-contrib/ngbatis/issues/329) 修正返回值类型并明确接口泛型。[#335](https://github.com/nebula-contrib/ngbatis/pull/335)
+- fix: 移除 JDK8 的内部 API: ParameterizedTypeImpl
+
+## 新特性
+
+- feat: 实体直接搜索。 ([#319](https://github.com/nebula-contrib/ngbatis/pull/319), 来自:[@xYLiuuuuuu](https://github.com/n3A87))
+ - 实体可以继承 `GraphBaseVertex` 或 `GraphBaseEdge` 来支持直接搜索。
+ - GraphBaseVertex:
+
+ API | 用法说明
+ --|--
+ queryIdsByProperties() | 查询特定Tag或者属性的点Id集合
+ queryVertexById() | 查询特定点Id的单个点
+ queryVertexByTag() | 查询特定Tag的点集合
+ queryVertexByProperties() | 查询特定属性的点集合
+ queryAllAdjacentVertex(Class>... edgeClass) | 查询特定点的所有邻点集合,可指定一个或多个连接两点的边类型
+ queryIncomingAdjacentVertex(Class>... edgeClass) | 查询特定点入边方向的邻点集合,可指定一个或多个连接两点的边类型
+ queryOutgoingAdjacentVertex(Class>... edgeClass) | 查询特定点出边方向的邻点集合,可指定一个或多个连接两点的边类型
+ queryNeighborIdsWithHopById(int m, int n, Class>... edgeClass) | 查询特定点指定跳数内的点Id集合,可指定一个或多个连接两点的边类型
+ queryConnectedEdgesById(Direction direction) | 查询特定点关联的所有边集合,可指定边的方向和类型
+ queryPathFromVertex(Direction direction) | 查询特定点关联的所有路径集合,可指定边的方向
+ queryFixedLengthPathFromVertex(Integer maxHop, Direction direction, Class>... edgeClass) | 查询特定点出发的定长路径集合,可指定最大步数、边的方向、边的类型
+ queryVariableLengthPathFromVertex(Integer minHop, Integer maxHop, Direction direction, Class>... edgeClass) | 查询特定点出发的变长路径集合,可指定最小步数、最大步数、边的方向、边的类型
+ queryShortestPathFromSrcAndDst(Integer maxHop, Direction direction, T v2) | 查询特定点出发的任意一条最短路径,可指定步数、边的方向、终点实体
+ queryAllShortestPathsFromSrcAndDst(Integer maxHop, Direction direction, T v2) | 查询从该点出发的所有最短路径集合,可指定步数、边的方向、终点实体
+ queryVertexCountByTag() | 查询特定Tag的点的数量
+
+ - GraphBaseEdge:
+
+ API | 用法说明
+ --|--
+ queryEdgeByType(Direction direction) | 查询特定类型、方向的边集合
+ queryEdgeWithSrcAndDstByProperties(T srcVertex, Direction direction, T dstVertex) | 查询特定属性的边集合
+ queryEdgePropertiesBySrcAndDstId() | 查询特定始终点id的边集合
+ queryEdgeCountByType() | 查询特定Type的边的数量
+
+- feat: 修复 [#324](https://github.com/nebulagraph/ngbatis/issues/324) 在 NebulaDaoBasic 中增加 insertForce(v) insertSelectiveForce(v)。[#335](https://github.com/nebula-contrib/ngbatis/pull/335)
+- feat: @Space 注解和 Mapper xml 中的 space 配置支持动态配置。 ([#318](https://github.com/nebula-contrib/ngbatis/pull/318), 来自:[@charle004](https://github.com/charle004))
+- feat: 支持 yml 中配置多个 mapper-locations。 ([#318](https://github.com/nebulagraph/ngbatis/pull/318), 来自:[@charle004](https://github.com/charle004))
+- feat: SessionPool 支持使用 `spaceFromParam`进行运行时的图空间切换,包括运行后才创建的图空间。
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f9bc847..cf7b141 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -28,6 +28,52 @@ This source code is licensed under Apache 2.0 License.
# NEXT
+# 2.0.0-beta
+
+## Bugfix
+
+- fix: [#329](https://github.com/nebula-contrib/ngbatis/issues/329) correct the return value type and clear the interface generic.[#335](https://github.com/nebula-contrib/ngbatis/pull/335)
+- fix: remove JDK8's internal API: ParameterizedTypeImpl
+
+## Feature
+
+- feat: Entity Direct Search. ([#319](https://github.com/nebula-contrib/ngbatis/pull/319), via: [@xYLiuuuuuu](https://github.com/n3A87))
+ - Entities can extend `GraphBaseVertex` or `GraphBaseEdge` to support direct search.
+ - GraphBaseVertex:
+
+ API | Usage instructions
+ --|--
+ queryIdsByProperties() | Query a collection of vertex ids for a particular Tag or attribute
+ queryVertexById() | Query a single vertex for a specific vertex Id
+ queryVertexByTag() | Query a collection of vertices for a specific Tag
+ queryVertexByProperties() | Query a collection of vertexes for a specific property
+ queryAllAdjacentVertex(Class>... edgeClass) | Query a collection of all neighboring vertexes of a particular vertex, specifying one or more edge types that connect the two vertexes
+ queryIncomingAdjacentVertex(Class>... edgeClass) | Query the set of adjacent vertexes in the direction of the incoming edge of a particular vertex, specifying one or more edge types that connect two vertexes
+ queryOutgoingAdjacentVertex(Class>... edgeClass) | Query the set of adjacent vertexes in the direction of the edge of a particular vertex, specifying one or more edge types that connect two vertexes
+ queryNeighborIdsWithHopById(int m, int n, Class>... edgeClass) | Query a collection of vertex ids within a specified number of hops for a particular vertex, specifying one or more edge types that connect two vertexes
+ queryConnectedEdgesById(Direction direction) | Query the set of all edges associated with a particular vertex, specifying the direction and type of the edge
+ queryPathFromVertex(Direction direction) | Query the collection of all paths associated with a particular vertex, specifying the direction of the edge
+ queryFixedLengthPathFromVertex(Integer maxHop, Direction direction, Class>... edgeClass) | Query a set of fixed-length paths from a specific vertex, specifying the maximum number of steps, the direction of the edge, and the type of the edge
+ queryVariableLengthPathFromVertex(Integer minHop, Integer maxHop, Direction direction, Class>... edgeClass) | Query a set of variable-length paths from a specific vertex, specifying the minimum number of steps, the maximum number of steps, the direction of the edge, and the type of the edge
+ queryShortestPathFromSrcAndDst(Integer maxHop, Direction direction, T v2) | Query any shortest path from a specific vertex, specifying the number of steps, the direction of the edge, and the end vertex entity
+ queryAllShortestPathsFromSrcAndDst(Integer maxHop, Direction direction, T v2) | Query the set of all shortest paths from this vertex, specifying the number of steps, the direction of the edge, and the end vertex entity
+ queryVertexCountByTag() | Query the number of vertexes for a specific Tag
+
+ - GraphBaseEdge:
+
+ API | Usage instructions
+ --|--
+ queryEdgeByType(Direction direction) | Query a set of edges of a specific type and direction
+ queryEdgeWithSrcAndDstByProperties(T srcVertex, Direction direction, T dstVertex) | Query a set of edges for a particular property
+ queryEdgePropertiesBySrcAndDstId() | Query a set of edges for a specific always vertex id
+ queryEdgeCountByType() | Query the number of edges for a specific Type
+
+- feat: fix [#324](https://github.com/nebulagraph/ngbatis/issues/324) add insertForce(v) insertSelectiveForce(v) into NebulaDaoBasic.[#335](https://github.com/nebula-contrib/ngbatis/pull/335)
+- feat: `@Space` annotation and space config in mapper xml supports dynamic configuration. ([#318](https://github.com/nebula-contrib/ngbatis/pull/318), via: [@charle004](https://github.com/charle004))
+ > `@Space` 注解的 name 属性值和 xml 文件中 Mapper 标签指定的 Space 可通过 spring 配置文件自定义配置。
+- feat: support multiple mapper-locations in yml. ([#318](https://github.com/nebula-contrib/ngbatis/pull/318), via: [@charle004](https://github.com/charle004))
+- feat: SessionPool support `spaceFromParam`.
+
# 1.3.0
## Dependencies upgrade
@@ -78,9 +124,9 @@ This source code is licensed under Apache 2.0 License.
Route-Tag: abc
```
-- feat: @Space annotation and space config in mapper xml supports dynamic configuration.
- > @Space 注解的 name 属性值和 xml 文件中 Mapper 标签指定的 Space 可通过 spring 配置文件自定义配置。
- - @Space example:
+- feat: `@Space` annotation supports dynamic configuration.
+ > `@Space` 注解的 name 属性值可通过 spring 配置文件自定义配置。
+ - example:
```yaml
app:
diff --git a/README-CN.md b/README-CN.md
index 4d5969c..4404384 100644
--- a/README-CN.md
+++ b/README-CN.md
@@ -347,13 +347,12 @@ public class PersonServiceImpl {
- 继承`GraphBaseVertex`类标识是点实体
- `@Tag`的name属性注明点实体的Tag
-- `@GraphId`的type属性注明点实体id的类型(可选)
```java
@Tag(name = "player")
public class Player extends GraphBaseVertex {
- @GraphId(type = IdType.STRING)
+ @Id
private String id;
private String name;
diff --git a/README.md b/README.md
index aabe26b..bd7dad6 100644
--- a/README.md
+++ b/README.md
@@ -34,6 +34,7 @@ See [EXECUTION-PROCESS.md](./EXECUTION-PROCESS.md)
NgBatis | nebula-java | JDK | Springboot | Beetl
---|-------------|---|------------|---
+ 2.0.0-beta | 3.8.3 | 8 | 2.7.0 | 3.15.10.RELEASE
1.3.0 | 3.8.3 | 8 | 2.7.0 | 3.15.10.RELEASE
1.3.0-jdk17 | 3.8.3 | 17 | 3.0.7 | 3.15.10.RELEASE
1.2.2 | 3.6.0 | 8 | 2.7.0 | 3.15.10.RELEASE
@@ -64,14 +65,14 @@ See [EXECUTION-PROCESS.md](./EXECUTION-PROCESS.md)
org.nebula-contrib
ngbatis
- 1.3.0
+ 2.0.0-beta
```
- Gradle
```groovy
- implementation 'org.nebula-contrib:ngbatis:1.3.0'
+ implementation 'org.nebula-contrib:ngbatis:2.0.0-beta'
```
- Referring to [ngbatis-demo](./ngbatis-demo), which was smoothly integrated with spring-boot. The API examples could be found under the test of it for all features of ngbatis.
@@ -347,14 +348,13 @@ public class PersonServiceImpl {
- Extends the `GraphBaseVertex` class identifier as a vertex entity
- The name attribute of `@Tag` indicates the Tag of the vertex entity
-- The type attribute of `@GraphId` indicates the type of the point entity id (optional)
```java
@Tag(name = "player")
public class Player extends GraphBaseVertex {
- @GraphId(type = IdType.STRING)
+ @Id
private String id;
private String name;
diff --git a/ngbatis-demo/pom.xml b/ngbatis-demo/pom.xml
index 098720a..b86c5eb 100644
--- a/ngbatis-demo/pom.xml
+++ b/ngbatis-demo/pom.xml
@@ -50,7 +50,7 @@
org.nebula-contrib
ngbatis
- 1.3.0
+ 2.0.0-beta
diff --git a/ngbatis-demo/src/main/java/ye/weicheng/ngbatis/demo/pojo/Paragraph.java b/ngbatis-demo/src/main/java/ye/weicheng/ngbatis/demo/pojo/Paragraph.java
new file mode 100644
index 0000000..3364f9b
--- /dev/null
+++ b/ngbatis-demo/src/main/java/ye/weicheng/ngbatis/demo/pojo/Paragraph.java
@@ -0,0 +1,35 @@
+package ye.weicheng.ngbatis.demo.pojo;
+
+// Copyright (c) 2024 All project authors. All rights reserved.
+//
+// This source code is licensed under Apache 2.0 License.
+
+import javax.persistence.Id;
+import javax.persistence.Table;
+import org.nebula.contrib.ngbatis.annotations.Space;
+
+@Table(name = "paragraph")
+@Space(name = "${nebula.ngbatis.test-space-placeholder}")
+public class Paragraph {
+
+ @Id
+ private Long id;
+
+ private String name;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+}
diff --git a/ngbatis-demo/src/main/java/ye/weicheng/ngbatis/demo/repository/ParagraphDao.java b/ngbatis-demo/src/main/java/ye/weicheng/ngbatis/demo/repository/ParagraphDao.java
new file mode 100644
index 0000000..a72e28f
--- /dev/null
+++ b/ngbatis-demo/src/main/java/ye/weicheng/ngbatis/demo/repository/ParagraphDao.java
@@ -0,0 +1,27 @@
+package ye.weicheng.ngbatis.demo.repository;
+
+// Copyright (c) 2024 All project authors. All rights reserved.
+//
+// This source code is licensed under Apache 2.0 License.
+
+import com.vesoft.nebula.client.graph.data.ResultSet;
+import org.nebula.contrib.ngbatis.annotations.Space;
+import org.nebula.contrib.ngbatis.proxy.NebulaDaoBasic;
+import org.springframework.data.repository.query.Param;
+import ye.weicheng.ngbatis.demo.pojo.Paragraph;
+
+/**
+ * @author yeweicheng
+ * @since 2024-12-19 9:30
+ *
Now is history!
+ */
+@Space(name = "${nebula.ngbatis.test-space-placeholder}")
+public interface ParagraphDao extends NebulaDaoBasic {
+
+ ResultSet testSpaceFromYml();
+
+ ResultSet testSpaceFromParam(@Param("spaceParam") String space);
+
+ ResultSet testSpaceAnno();
+
+}
diff --git a/ngbatis-demo/src/main/resources/application.yml b/ngbatis-demo/src/main/resources/application.yml
index 5278acd..2647fca 100644
--- a/ngbatis-demo/src/main/resources/application.yml
+++ b/ngbatis-demo/src/main/resources/application.yml
@@ -12,6 +12,7 @@ nebula:
# space name needs to be informed through annotations(@Space) or xml(space="test")
# default false(false: Session pool map will not be initialized)
use-session-pool: true
+ test-space-placeholder: cmqa
hosts: 139.9.187.207:9669
username: root
password: U3RhclNoYWRvd18wOTE5
diff --git a/ngbatis-demo/src/main/resources/mapper/ParagraphDao.xml b/ngbatis-demo/src/main/resources/mapper/ParagraphDao.xml
new file mode 100644
index 0000000..e2f7fd3
--- /dev/null
+++ b/ngbatis-demo/src/main/resources/mapper/ParagraphDao.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/ngbatis-demo/src/test/java/ye/weicheng/ngbatis/demo/NebulaGraphBasicTests.java b/ngbatis-demo/src/test/java/ye/weicheng/ngbatis/demo/NebulaGraphBasicTests.java
index ede19a0..2521fb5 100644
--- a/ngbatis-demo/src/test/java/ye/weicheng/ngbatis/demo/NebulaGraphBasicTests.java
+++ b/ngbatis-demo/src/test/java/ye/weicheng/ngbatis/demo/NebulaGraphBasicTests.java
@@ -94,7 +94,7 @@ public void queryOutgoingAdjacentVertex() {
}
}
- @Test
+ // @Test
public void queryNeighborIdsWithHopById() {
Player player = new Player();
player.setId("player102");
@@ -157,7 +157,7 @@ public void queryVariableLengthPath() {
}
- @Test
+ // @Test
public void queryShortestPathFromSrcAndDst() {
Player src = new Player();
src.setName("Tim Duncan");
@@ -168,7 +168,7 @@ public void queryShortestPathFromSrcAndDst() {
}
- @Test
+ // @Test
public void queryAllShortestPathsFromSrcAndDst() {
Player src = new Player();
src.setName("Tim Duncan");
diff --git a/ngbatis-demo/src/test/java/ye/weicheng/ngbatis/demo/repository/ParagraphDaoTest.java b/ngbatis-demo/src/test/java/ye/weicheng/ngbatis/demo/repository/ParagraphDaoTest.java
new file mode 100644
index 0000000..02c1d06
--- /dev/null
+++ b/ngbatis-demo/src/test/java/ye/weicheng/ngbatis/demo/repository/ParagraphDaoTest.java
@@ -0,0 +1,63 @@
+package ye.weicheng.ngbatis.demo.repository;
+
+// Copyright (c) 2024 All project authors. All rights reserved.
+//
+// This source code is licensed under Apache 2.0 License.
+
+import com.vesoft.nebula.client.graph.data.ResultSet;
+import org.junit.jupiter.api.MethodOrderer.OrderAnnotation;
+import org.junit.jupiter.api.Order;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestMethodOrder;
+import org.locationtech.jts.util.Assert;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import ye.weicheng.ngbatis.demo.pojo.Paragraph;
+
+/**
+ * @author yeweicheng
+ * @since 2024-12-19 9:37
+ *
Now is history!
+ */
+@SpringBootTest
+@TestMethodOrder(OrderAnnotation.class)
+class ParagraphDaoTest {
+ @Autowired
+ private ParagraphDao dao;
+
+ @Test
+ @Order(1)
+ public void testSpace() {
+ ResultSet rs = dao.testSpaceFromYml();
+ Assert.equals(rs.getSpaceName(), "test");
+ }
+
+ @Test
+ @Order(2)
+ public void testSpaceFromParam() {
+ ResultSet rs = dao.testSpaceFromParam("test");
+ Assert.equals(rs.getSpaceName(), "test");
+ }
+
+ @Test
+ @Order(3)
+ public void testSpaceFromParam2() {
+ ResultSet rs = dao.testSpaceFromParam("${nebula.ngbatis.test-space-placeholder}");
+ Assert.equals(rs.getSpaceName(), "cmqa");
+ }
+
+ @Test
+ @Order(4)
+ public void testSpaceAnno() {
+ ResultSet rs = dao.testSpaceAnno();
+ Assert.equals(rs.getSpaceName(), "cmqa");
+ }
+
+ @Test
+ @Order(5)
+ public void testSelectById() {
+ Paragraph pageable = dao.selectById(0);
+ // 观察日志的 session space, 为 cmqa
+ }
+
+}
diff --git a/pom.xml b/pom.xml
index 734951b..4d8d3d9 100644
--- a/pom.xml
+++ b/pom.xml
@@ -13,7 +13,7 @@
ngbatis
org.nebula-contrib
ngbatis
- 1.3.0-snapshot
+ 2.0.0-beta
NgBatis is a database ORM framework base NebulaGraph + spring-boot,
@@ -157,6 +157,17 @@
+
+ org.sonatype.plugins
+ nexus-staging-maven-plugin
+ 1.6.13
+ true
+
+ ossrh
+ https://s01.oss.sonatype.org
+ true
+
+
@@ -385,12 +396,14 @@
- nexus-releases
- http://172.17.10.100:8081/nexus/content/repositories/releases
+ ossrh
+ Nexus Release Repository
+ https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/
- nexus-snapshots
- http://172.17.10.100:8081/nexus/content/repositories/snapshots
+ ossrh
+ Nexus Snapshot Repository
+ https://s01.oss.sonatype.org/content/repositories/snapshots
diff --git a/src/main/java/org/nebula/contrib/ngbatis/Env.java b/src/main/java/org/nebula/contrib/ngbatis/Env.java
index 9c35b48..76824ff 100644
--- a/src/main/java/org/nebula/contrib/ngbatis/Env.java
+++ b/src/main/java/org/nebula/contrib/ngbatis/Env.java
@@ -4,16 +4,11 @@
//
// This source code is licensed under Apache 2.0 License.
-import static org.apache.commons.lang3.StringUtils.isBlank;
-import static org.nebula.contrib.ngbatis.proxy.MapperProxy.ENV;
-import static org.nebula.contrib.ngbatis.utils.ReflectUtil.spaceFromEntity;
-
import com.alibaba.fastjson.parser.ParserConfig;
import com.vesoft.nebula.client.graph.SessionPool;
import com.vesoft.nebula.client.graph.net.Session;
import org.nebula.contrib.ngbatis.base.GraphBaseExt;
import org.nebula.contrib.ngbatis.config.ParseCfgProps;
-import org.nebula.contrib.ngbatis.exception.ResourceLoadException;
import org.nebula.contrib.ngbatis.models.MapperContext;
import org.nebula.contrib.ngbatis.proxy.MapperProxy;
import org.slf4j.Logger;
@@ -127,56 +122,6 @@ public Session openSession() {
}
}
- /**
- * 通过实体类获取对应的space。
- * 支持占位符,并从配置信息中读取。
- *
- * @param entityType 实体类
- * @return space
- */
- public static String spaceFromConfig(Class> entityType) {
- return spaceFromConfig(entityType, ENV.getContext());
- }
-
- public static String spaceFromConfig(Class> entityType, ApplicationContext context) {
- String space = spaceFromEntity(entityType);
- if (isBlank(space)) return null;
- space = tryResolvePlaceholder(space, context);
- return space;
- }
-
- /**
- * 利用Spring Environment 解析注解的值,用于 @Space 的 name 属性解析
- * @author Charle004
- * @param value 需要解析的值,可能是带占位符的 ${xx.xx} ,也可以是固定的字符串
- * @return resolveResult 解析结果
- * @throws IllegalArgumentException 当配置了 ${xx.xx} 占位符,且spring配置文件中未指定该配置时抛出
- */
- public static String tryResolvePlaceholder(String value) {
- return tryResolvePlaceholder(value, ENV.getContext());
- }
-
- /**
- * 利用Spring Environment 解析注解的值,用于 @Space 的 name 属性解析
- * @author Charle004
- * @param configKey 需要解析的值,可能是带占位符的 ${xx.xx} ,也可以是固定的字符串
- * @return resolveResult 解析结果
- * @throws IllegalArgumentException 当配置了 ${xx.xx} 占位符,且spring配置文件中未指定该配置时抛出
- */
- public static String tryResolvePlaceholder(String configKey, ApplicationContext context) {
- String resolveResult = configKey;
- if (null != context) {
- try {
- resolveResult = context.getEnvironment().resolveRequiredPlaceholders(configKey);
- } catch (IllegalArgumentException e) {
- throw new ResourceLoadException(
- "name ( " + configKey + " ) of @Space missing configurable value"
- );
- }
- }
- return resolveResult;
- }
-
public String getUsername() {
return username;
}
diff --git a/src/main/java/org/nebula/contrib/ngbatis/NgbatisBeanFactoryPostProcessor.java b/src/main/java/org/nebula/contrib/ngbatis/NgbatisBeanFactoryPostProcessor.java
index 9d37de0..0c7a0aa 100644
--- a/src/main/java/org/nebula/contrib/ngbatis/NgbatisBeanFactoryPostProcessor.java
+++ b/src/main/java/org/nebula/contrib/ngbatis/NgbatisBeanFactoryPostProcessor.java
@@ -2,6 +2,7 @@
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import static org.nebula.contrib.ngbatis.models.ClassModel.PROXY_SUFFIX;
+import static org.nebula.contrib.ngbatis.proxy.MapperProxy.ENV;
import static org.nebula.contrib.ngbatis.proxy.NebulaDaoBasicExt.entityTypeAndIdType;
import static org.nebula.contrib.ngbatis.proxy.NebulaDaoBasicExt.vertexName;
@@ -195,26 +196,22 @@ public NebulaPool nebulaPool() {
/**
* create and init Nebula SessionPool
+ * please use IntervalCheckSessionDispatcher.setNebulaSessionPool() instead.
*/
@Deprecated
- public void setNebulaSessionPool(MapperContext context) throws Exception {
- throw new Exception(
- "Deprecated method, "
- + "please use IntervalCheckSessionDispatcher.setNebulaSessionPool() instead."
- );
+ public void setNebulaSessionPool(MapperContext context) {
+ ENV.getDispatcher().setNebulaSessionPool(context);
}
/**
* session pool create and init
+ * please use IntervalCheckSessionDispatcher.initSessionPool() instead.
* @param spaceName nebula space name
* @return inited SessionPool
*/
@Deprecated
- public SessionPool initSessionPool(String spaceName) throws Exception {
- throw new Exception(
- "Deprecated method, "
- + "please use SessionDispatcher.initSessionPool() instead."
- );
+ public SessionPool initSessionPool(String spaceName) {
+ return ENV.getDispatcher().initSessionPool(spaceName);
}
@Override
diff --git a/src/main/java/org/nebula/contrib/ngbatis/SessionDispatcher.java b/src/main/java/org/nebula/contrib/ngbatis/SessionDispatcher.java
index fab8a61..ae76e81 100644
--- a/src/main/java/org/nebula/contrib/ngbatis/SessionDispatcher.java
+++ b/src/main/java/org/nebula/contrib/ngbatis/SessionDispatcher.java
@@ -72,6 +72,8 @@ static boolean useSessionPool() {
return ngbatisConfig != null && ngbatisConfig.getUseSessionPool();
}
+ void setNebulaSessionPool(MapperContext context);
+
/**
* 按 spaceName 初始化 sessionPool
*
diff --git a/src/main/java/org/nebula/contrib/ngbatis/base/GraphBaseExt.java b/src/main/java/org/nebula/contrib/ngbatis/base/GraphBaseExt.java
index 981517c..cd14cb9 100644
--- a/src/main/java/org/nebula/contrib/ngbatis/base/GraphBaseExt.java
+++ b/src/main/java/org/nebula/contrib/ngbatis/base/GraphBaseExt.java
@@ -1,6 +1,5 @@
package org.nebula.contrib.ngbatis.base;
-import static org.nebula.contrib.ngbatis.Env.spaceFromConfig;
import static org.nebula.contrib.ngbatis.utils.ReflectUtil.getNameByColumn;
import static org.nebula.contrib.ngbatis.utils.ReflectUtil.getValue;
@@ -15,6 +14,7 @@
import org.nebula.contrib.ngbatis.SessionDispatcher;
import org.nebula.contrib.ngbatis.annotations.base.EdgeType;
import org.nebula.contrib.ngbatis.annotations.base.Tag;
+import org.nebula.contrib.ngbatis.session.SpaceRouter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -34,7 +34,7 @@ public static ResultSet executeGql(String textTpl,
//从env中获取本地会话调度器
SessionDispatcher dispatcher = ENV.getDispatcher();
//从env中获取space
- String currentSpace = getSpace(m1);
+ String currentSpace = SpaceRouter.getSpace(m1);
ArgsResolver argsResolver = ENV.getArgsResolver();
@@ -57,38 +57,6 @@ public static ResultSet executeGql(String textTpl,
return result;
}
- /**
- * 获取当前space,支持 @Space 跟 @Table 注解
- * 如果均未指定,则返回默认space
- *
- * @return 当前space
- */
- public static String getSpace(Map m1) {
- Object edgeType = m1.get("edgeType");
- Object tag = m1.get("tag");
- String entityTypeName = edgeType != null ? edgeType.toString()
- : tag != null ? tag.toString()
- : null;
-
- String defaultSpace = ENV.getSpace();
- if (entityTypeName == null) {
- return defaultSpace;
- }
-
- Map> entityTypeMapping = ENV.getMapperContext().getTagTypeMapping();
- Class> entityType = entityTypeMapping.get(entityTypeName);
- boolean isGraphBase = GraphBase.class.isAssignableFrom(entityType);
- if (!isGraphBase) {
- return defaultSpace;
- }
-
- String space = spaceFromConfig(entityType);
- if (space != null) {
- return space;
- }
- return ENV.getSpace();
- }
-
/**
* 处理查询结果
* @param resultSet 结果集ResultSet
diff --git a/src/main/java/org/nebula/contrib/ngbatis/io/MapperResourceLoader.java b/src/main/java/org/nebula/contrib/ngbatis/io/MapperResourceLoader.java
index 578966d..fbcd111 100644
--- a/src/main/java/org/nebula/contrib/ngbatis/io/MapperResourceLoader.java
+++ b/src/main/java/org/nebula/contrib/ngbatis/io/MapperResourceLoader.java
@@ -6,7 +6,6 @@
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
-import static org.nebula.contrib.ngbatis.SessionDispatcher.addSpaceToSessionPool;
import static org.nebula.contrib.ngbatis.models.ClassModel.PROXY_SUFFIX;
import static org.nebula.contrib.ngbatis.utils.ReflectUtil.NEED_SEALING_TYPES;
import static org.nebula.contrib.ngbatis.utils.ReflectUtil.getNameUniqueMethod;
@@ -16,8 +15,6 @@
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
@@ -31,8 +28,6 @@
import org.jsoup.nodes.Node;
import org.jsoup.nodes.TextNode;
import org.jsoup.select.Elements;
-import org.nebula.contrib.ngbatis.Env;
-import org.nebula.contrib.ngbatis.annotations.Space;
import org.nebula.contrib.ngbatis.annotations.TimeLog;
import org.nebula.contrib.ngbatis.config.ParseCfgProps;
import org.nebula.contrib.ngbatis.exception.ParseException;
@@ -42,6 +37,7 @@
import org.nebula.contrib.ngbatis.models.NgqlModel;
import org.nebula.contrib.ngbatis.utils.Page;
import org.nebula.contrib.ngbatis.utils.ReflectUtil;
+import org.nebula.contrib.ngbatis.session.SpaceRouter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
@@ -126,13 +122,7 @@ public Map parseClassModel(Resource resource)
match(cm, element, "space", parseConfig.getSpace());
// 从注解获取 space
- if (null == cm.getSpace()) {
- setClassModelBySpaceAnnotation(cm);
- }else {
- //动态解析 XML 中 mapper 标签配置的 Space 属性
- setClassModelByXmlConfigSpace(cm);
- }
- addSpaceToSessionPool(cm.getSpace());
+ SpaceRouter.setClassSpace(cm, applicationContext);
// 获取 子节点
List nodes = element.childNodes();
@@ -144,42 +134,6 @@ public Map parseClassModel(Resource resource)
return result;
}
- /**
- * 解析自定义的 XML 中的 mapper 标签设置的 space
- * @param cm ClassModel
- */
- private void setClassModelByXmlConfigSpace(ClassModel cm) {
- String space = tryResolvePlaceholder(cm.getSpace());
- cm.setSpace(space);
- }
-
- /**
- * 设置 space
- * @param cm ClassModel
- */
- private void setClassModelBySpaceAnnotation(ClassModel cm) {
- try {
- Type[] genericInterfaces = cm.getNamespace().getGenericInterfaces();
- if (genericInterfaces.length == 0) {
- return;
- }
- ParameterizedType nebulaDaoBasicType = (ParameterizedType) genericInterfaces[0];
- Type[] genericTypes = nebulaDaoBasicType.getActualTypeArguments();
- if (genericTypes.length == 0) {
- return;
- }
- String spaceClassName = genericTypes[0].getTypeName();
- Class> entityType = Class.forName(spaceClassName);
- String space = ReflectUtil.spaceFromEntity(entityType);
- if (isNotBlank(space)) {
- space = Env.tryResolvePlaceholder(space, applicationContext);
- cm.setSpace(space);
- }
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- }
- }
-
/**
* 解析 一个 XXXDao 的多个方法。
*
@@ -203,9 +157,7 @@ private Map parseMethodModel(ClassModel cm, List node
cm.getNgqls().put(ngqlModel.getId(),ngqlModel);
} else {
MethodModel methodModel = parseMethodModel(methodNode);
- if (!methodModel.isSpaceFromParam()) {
- addSpaceToSessionPool(methodModel.getSpace());
- }
+ SpaceRouter.setMethodSpace(methodModel, applicationContext);
Method method = getNameUniqueMethod(namespace, methodModel.getId());
methodModel.setMethod(method);
Assert.notNull(method,
diff --git a/src/main/java/org/nebula/contrib/ngbatis/models/MapperContext.java b/src/main/java/org/nebula/contrib/ngbatis/models/MapperContext.java
index daf9f96..f74ba9c 100644
--- a/src/main/java/org/nebula/contrib/ngbatis/models/MapperContext.java
+++ b/src/main/java/org/nebula/contrib/ngbatis/models/MapperContext.java
@@ -4,6 +4,8 @@
//
// This source code is licensed under Apache 2.0 License.
+import static org.nebula.contrib.ngbatis.utils.ReflectUtil.typeArg;
+
import com.vesoft.nebula.client.graph.NebulaPoolConfig;
import com.vesoft.nebula.client.graph.SessionPool;
import com.vesoft.nebula.client.graph.net.NebulaPool;
@@ -13,6 +15,7 @@
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.nebula.contrib.ngbatis.config.NgbatisConfig;
+import org.nebula.contrib.ngbatis.proxy.NebulaDaoBasic;
/**
* xml 中标签所声明的信息(方法)
@@ -30,6 +33,10 @@ public class MapperContext {
final Map> tagTypeMapping = new HashMap<>();
/**
* 当前应用中,在 xml 中 namespace 所声明的所有 XXXDao 及其 类模型
+ *
+ * - key: bean名称,自定义DAO接口名+{@link ClassModel.PROXY_SUFFIX}
+ * - value: 类模型
+ *
*/
Map interfaces;
/**
@@ -59,6 +66,11 @@ public class MapperContext {
private NgbatisConfig ngbatisConfig;
boolean resourceRefresh = false;
+ /**
+ * 实体类名与类模型的映射
+ */
+ private Map, ClassModel> entityClassModelMap = null;
+
private MapperContext() {
}
@@ -141,4 +153,16 @@ public Map> getTagTypeMapping() {
return tagTypeMapping;
}
+ public Map, ClassModel> computeEntityClassModelMap() {
+ if (entityClassModelMap == null) {
+ entityClassModelMap = new HashMap<>();
+ for (ClassModel classModel : interfaces.values()) {
+ Class> entityType = typeArg(classModel.getNamespace(), NebulaDaoBasic.class, 0);
+ if (entityType != null) {
+ entityClassModelMap.put(entityType, classModel);
+ }
+ }
+ }
+ return entityClassModelMap;
+ }
}
diff --git a/src/main/java/org/nebula/contrib/ngbatis/proxy/MapperProxy.java b/src/main/java/org/nebula/contrib/ngbatis/proxy/MapperProxy.java
index eb42bb1..88c10ad 100644
--- a/src/main/java/org/nebula/contrib/ngbatis/proxy/MapperProxy.java
+++ b/src/main/java/org/nebula/contrib/ngbatis/proxy/MapperProxy.java
@@ -5,35 +5,27 @@
// This source code is licensed under Apache 2.0 License.
import static org.apache.commons.lang3.ObjectUtils.isEmpty;
-import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.nebula.contrib.ngbatis.models.ClassModel.PROXY_SUFFIX;
-import com.vesoft.nebula.client.graph.SessionPool;
import com.vesoft.nebula.client.graph.data.ResultSet;
-import com.vesoft.nebula.client.graph.exception.BindSpaceFailedException;
-import com.vesoft.nebula.client.graph.exception.IOErrorException;
-import com.vesoft.nebula.client.graph.net.Session;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
-import java.util.Objects;
import org.nebula.contrib.ngbatis.ArgsResolver;
import org.nebula.contrib.ngbatis.Env;
import org.nebula.contrib.ngbatis.ResultResolver;
import org.nebula.contrib.ngbatis.SessionDispatcher;
-import org.nebula.contrib.ngbatis.config.NgbatisConfig;
import org.nebula.contrib.ngbatis.config.ParseCfgProps;
import org.nebula.contrib.ngbatis.exception.QueryException;
import org.nebula.contrib.ngbatis.models.ClassModel;
import org.nebula.contrib.ngbatis.models.MapperContext;
import org.nebula.contrib.ngbatis.models.MethodModel;
-import org.nebula.contrib.ngbatis.session.LocalSession;
import org.nebula.contrib.ngbatis.utils.Page;
import org.nebula.contrib.ngbatis.utils.ReflectUtil;
-import org.nebula.contrib.ngbatis.utils.ResultSetUtil;
+import org.nebula.contrib.ngbatis.session.SpaceRouter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -220,7 +212,7 @@ public static ResultSet executeWithParameter(
proxyMethod = mm.getId();
}
- String currentSpace = getSpace(cm, mm, paramsForTemplate);
+ String currentSpace = SpaceRouter.getSpace(cm, mm, paramsForTemplate);
result = dispatcher.executeWithParameter(
gql, params, currentSpace, extraReturn
);
@@ -252,88 +244,79 @@ public static ResultSet executeWithParameter(
}
}
- /**
- * 通过 nebula-graph 客户端执行数据库访问。被 invoke 所调用,间接为动态代理类服务。
- *
- * @param gql 待执行的查询脚本(模板)
- * @param params 待执行脚本的参数所需的参数
- * @return nebula-graph 的未被 orm 操作的原始结果集
- */
- public static ResultSet executeBySessionPool(ClassModel cm, MethodModel mm, String gql,
- Map params, Map paramsForTemplate) {
-
- ResultSet result = null;
- String proxyClass = null;
- String proxyMethod = null;
- String currentSpace = null;
-
- try {
- if (log.isDebugEnabled()) {
- proxyClass = cm.getNamespace().getName();
- proxyMethod = mm.getId();
- }
-
- currentSpace = getSpace(cm, mm, paramsForTemplate);
- SessionPool sessionPool = ENV.getSessionPool(currentSpace);
- if (sessionPool == null) {
- throw new QueryException(currentSpace + " sessionPool is null");
- }
- result = sessionPool.execute(gql, params);
- if (result.isSucceeded()) {
- return result;
- } else {
- throw new QueryException(
- " ResultSet error: " + result.getErrorMessage(),
- result.getErrorCode()
- );
- }
- } catch (Exception e) {
- throw new QueryException("execute failed: " + e.getMessage(), e);
- } finally {
- if (log.isDebugEnabled()) {
- log.debug("\n\t- proxyMethod: {}#{}"
- + "\n\t- session space: {}"
- + "\n\t- nGql:{}"
- + "\n\t- params: {}"
- + "\n\t- result:{}",
- proxyClass, proxyMethod, currentSpace, gql, paramsForTemplate, result);
- }
- }
- }
-
- /**
- * 获取当前语句所执行的目标space。
- * @param cm 当前接口的类模型
- * @param mm 当前接口方法的方法模型
- * @return 目标space
- */
- public static String getSpace(ClassModel cm, MethodModel mm) {
- String methodSpace;
- return (mm != null && (methodSpace = mm.getSpace()) != null)
- ? (
- "null".equals(methodSpace.trim()) ? null : methodSpace
- )
- : cm != null && cm.getSpace() != null ? cm.getSpace()
- : ENV.getSpace();
- }
-
- /**
- * 支持space从参数中获取
- * @param cm 当前接口的类模型
- * @param mm 当前接口方法的方法模型
- * @param paramsForTemplate 从模板参数中获取空间名
- * @return 目标space
- */
- public static String getSpace(
- ClassModel cm, MethodModel mm, Map paramsForTemplate
- ) {
- boolean spaceFromParam = mm.isSpaceFromParam();
- String space = getSpace(cm, mm);
- if (spaceFromParam && space != null) {
- return ENV.getTextResolver().resolve(space, paramsForTemplate);
- }
- return space;
- }
+// /**
+// * 通过 nebula-graph 客户端执行数据库访问。被 invoke 所调用,间接为动态代理类服务。
+// *
+// * @param gql 待执行的查询脚本(模板)
+// * @param params 待执行脚本的参数所需的参数
+// * @return nebula-graph 的未被 orm 操作的原始结果集
+// */
+// public static ResultSet executeBySessionPool(ClassModel cm, MethodModel mm, String gql,
+// Map params, Map paramsForTemplate) {
+//
+// ResultSet result = null;
+// String proxyClass = null;
+// String proxyMethod = null;
+// String currentSpace = null;
+//
+// try {
+// if (log.isDebugEnabled()) {
+// proxyClass = cm.getNamespace().getName();
+// proxyMethod = mm.getId();
+// }
+//
+// currentSpace = SpaceRouter.getSpace(cm, mm, paramsForTemplate);
+// SessionPool sessionPool = ENV.getSessionPool(currentSpace);
+// if (sessionPool == null) {
+// throw new QueryException(currentSpace + " sessionPool is null");
+// }
+// result = sessionPool.execute(gql, params);
+// if (result.isSucceeded()) {
+// return result;
+// } else {
+// throw new QueryException(
+// " ResultSet error: " + result.getErrorMessage(),
+// result.getErrorCode()
+// );
+// }
+// } catch (Exception e) {
+// throw new QueryException("execute failed: " + e.getMessage(), e);
+// } finally {
+// if (log.isDebugEnabled()) {
+// log.debug("\n\t- proxyMethod: {}#{}"
+// + "\n\t- session space: {}"
+// + "\n\t- nGql:{}"
+// + "\n\t- params: {}"
+// + "\n\t- result:{}",
+// proxyClass, proxyMethod, currentSpace, gql, paramsForTemplate, result);
+// }
+// }
+// }
+
+// /**
+// * 获取当前语句所执行的目标space。
+// * @param cm 当前接口的类模型
+// * @param mm 当前接口方法的方法模型
+// * @return 目标space
+// */
+// @Deprecated
+// public static String getSpace(ClassModel cm, MethodModel mm) {
+// return SpaceRouter.getSpace(cm, mm);
+// }
+
+// /**
+// * 支持space从参数中获取
+// * @param cm 当前接口的类模型
+// * @param mm 当前接口方法的方法模型
+// * @param paramsForTemplate 从模板参数中获取空间名
+// * @return 目标space
+// */
+// @Deprecated
+// public static String getSpace(
+// ClassModel cm, MethodModel mm, Map paramsForTemplate
+// ) {
+// return SpaceRouter.getSpace(cm, mm, paramsForTemplate);
+// }
public static Logger getLog() {
return log;
diff --git a/src/main/java/org/nebula/contrib/ngbatis/session/IntervalCheckSessionDispatcher.java b/src/main/java/org/nebula/contrib/ngbatis/session/IntervalCheckSessionDispatcher.java
index 4c09b56..6123c90 100644
--- a/src/main/java/org/nebula/contrib/ngbatis/session/IntervalCheckSessionDispatcher.java
+++ b/src/main/java/org/nebula/contrib/ngbatis/session/IntervalCheckSessionDispatcher.java
@@ -6,6 +6,7 @@
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.nebula.contrib.ngbatis.proxy.MapperProxy.ENV;
+import static org.springframework.util.ObjectUtils.nullSafeEquals;
import com.vesoft.nebula.client.graph.NebulaPoolConfig;
import com.vesoft.nebula.client.graph.SessionPool;
@@ -166,6 +167,7 @@ public boolean timeToRelease(LocalSession session) {
* @author gin soul [create]
* @author CorvusYe [refac]
*/
+ @Override
public void setNebulaSessionPool(MapperContext context) {
NgbatisConfig ngbatisConfig = nebulaJdbcProperties.getNgbatis();
if (ngbatisConfig.getUseSessionPool() == null || !ngbatisConfig.getUseSessionPool()) {
@@ -190,7 +192,6 @@ public void setNebulaSessionPool(MapperContext context) {
* @param spaceName nebula
space name
* @author gin soul [create]
- * @author CorvusYe [refac]
* @return inited SessionPool
*/
@Override
@@ -269,12 +270,15 @@ public ResultSet executeWithParameter(
String autoSwitch = qlAndSpace[0] == null ? "" : qlAndSpace[0];
session = localSession.getSession();
result = session.executeWithParameter(gql, params);
- extraReturn.put("autoSwitch", autoSwitch);
+
localSession.setCurrentSpace(getSpace(result));
handleSession(localSession, result);
if (log.isDebugEnabled()) {
- extraReturn.put("localSessionSpace", localSession.getCurrentSpace());
- extraReturn.put("autoSwitch", autoSwitch);
+ extraReturn.put("localSessionSpace", space);
+ String currentSpace = localSession.getCurrentSpace();
+ if (nullSafeEquals(currentSpace, autoSwitch)) {
+ extraReturn.put("autoSwitch", autoSwitch);
+ }
}
return result;
}
diff --git a/src/main/java/org/nebula/contrib/ngbatis/session/SpaceRouter.java b/src/main/java/org/nebula/contrib/ngbatis/session/SpaceRouter.java
new file mode 100644
index 0000000..8651869
--- /dev/null
+++ b/src/main/java/org/nebula/contrib/ngbatis/session/SpaceRouter.java
@@ -0,0 +1,239 @@
+package org.nebula.contrib.ngbatis.session;
+
+// Copyright (c) 2024 All project authors. All rights reserved.
+//
+// This source code is licensed under Apache 2.0 License.
+
+import static org.apache.commons.lang3.StringUtils.isBlank;
+import static org.apache.commons.lang3.StringUtils.isNotBlank;
+import static org.nebula.contrib.ngbatis.SessionDispatcher.addSpaceToSessionPool;
+import static org.nebula.contrib.ngbatis.proxy.MapperProxy.ENV;
+import static org.nebula.contrib.ngbatis.utils.ReflectUtil.typeArg;
+
+import java.util.Map;
+import javax.persistence.Table;
+import org.nebula.contrib.ngbatis.annotations.Space;
+import org.nebula.contrib.ngbatis.base.GraphBase;
+import org.nebula.contrib.ngbatis.exception.ResourceLoadException;
+import org.nebula.contrib.ngbatis.models.ClassModel;
+import org.nebula.contrib.ngbatis.models.MethodModel;
+import org.nebula.contrib.ngbatis.proxy.NebulaDaoBasic;
+import org.springframework.context.ApplicationContext;
+
+/**
+ * 用于处理读取空间配置相关的工具类
+ *
+ * @author yeweicheng
+ * @since 2024-12-20 23:26
+ *
Now is history!
+ */
+public class SpaceRouter {
+
+ /**
+ * 从实体类获取 space,并解析占位符 从类获取有两种来源:
+ *
+ * - 通过 @Table 注解
+ * - 通过 @Space 注解
+ * - 默认值:${ nebula.space }
+ * - 优先级:@Table > @Space > 默认值
+ * - 支持来自配置文件的占位符解析
+ * - 推荐使用 @Table,@Space 属于自定义注解,可能会在后续版本移除
+ *
+ */
+ public static String spaceFromEntity(Class> entityType) {
+ String defaultSpace = ENV == null ? null : ENV.getSpace();
+ if (entityType == null) {
+ return defaultSpace;
+ }
+
+ boolean hasTable = entityType.isAnnotationPresent(Table.class);
+ if (hasTable) {
+ Table tableAnnotation = entityType.getAnnotation(Table.class);
+ String space = tableAnnotation.schema();
+ System.out.println("table space: " + space);
+ if (isNotBlank(space)) {
+ return space;
+ }
+ }
+
+ boolean hasSpace = entityType.isAnnotationPresent(Space.class);
+
+ if (hasSpace) {
+ Space spaceAnnotation = entityType.getAnnotation(Space.class);
+ String space = spaceAnnotation.name();
+ if (isNotBlank(space)) {
+ System.out.println("space: " + space);
+ return space;
+ }
+ }
+
+ return defaultSpace;
+ }
+
+ public static String spaceFromEntity(Class> entityType, ApplicationContext context) {
+ String space = spaceFromEntity(entityType);
+ return tryResolvePlaceholder(space, context);
+ }
+
+ /**
+ * 通过DAO的类模型获取对应的space。 支持占位符,并从配置信息中读取。 在 xml 资源解析阶段调用,读取 space, 若 space 存在占位符,则解析占位符 并将解析后的
+ * space 设置到类模型中 此时,space 已经用上配置值,是有效的图空间。 并以此空间名初始化 session pool,如果开启了 session pool
+ *
+ * @param cm 类模型
+ */
+ public static void setClassSpace(ClassModel cm, ApplicationContext context) {
+ if (cm != null) {
+ String space = cm.getSpace();
+ if (isBlank(space)) {
+ Class> daoClass = cm.getNamespace();
+ // 从 dao 类的泛型中获取实体类
+ Class> entityType = typeArg(daoClass, NebulaDaoBasic.class, 0);
+ // 通过实体类的注解获取space
+ space = spaceFromEntity(entityType, context);
+ }
+ cm.setSpace(space);
+ addSpaceToSessionPool(cm.getSpace());
+ }
+ }
+
+ /**
+ * 设置不同接口方法的空间 未使用参数传递空间时,从配置文件中读取
+ *
+ * @param methodModel 方法模型
+ * @param applicationContext 应用上下文
+ */
+ public static void setMethodSpace(
+ MethodModel methodModel, ApplicationContext applicationContext) {
+ if (!methodModel.isSpaceFromParam()) { // 未使用参数传递空间
+ String space = methodModel.getSpace();
+ if (isNotBlank(space)) {
+ // 如果不为空,则尝试解析占位符
+ space = tryResolvePlaceholder(space, applicationContext);
+ methodModel.setSpace(space);
+ addSpaceToSessionPool(space);
+ }
+ }
+ }
+
+ /**
+ * 支持space从参数中获取
+ *
+ * @param cm 当前接口的类模型
+ * @param mm 当前接口方法的方法模型
+ * @param paramsForTemplate 从模板参数中获取空间名
+ * @return 目标space
+ */
+ public static String getSpace(
+ ClassModel cm, MethodModel mm, Map paramsForTemplate
+ ) {
+ boolean spaceFromParam = mm.isSpaceFromParam();
+ String space = mm.getSpace() != null ? mm.getSpace() : cm.getSpace();
+ if ("null".equals(space)) {
+ space = ENV.getSpace();;
+ }
+ if (spaceFromParam && space != null) {
+ // 从参数中获取space
+ String paramSpace = ENV.getTextResolver().resolve(space, paramsForTemplate);
+ // 让参数同样支持 ${xx.xx} 占位符
+ return tryResolvePlaceholder(paramSpace);
+ }
+ return isBlank(space) ? ENV.getSpace() : space;
+ }
+
+ /**
+ * 获取当前space,支持 @Space 跟 @Table 注解 如果均未指定,
+ * 则返回默认space 用于 GraphBaseExt 通过标签名、边类型名称获取space
+ *
+ * @return 当前space
+ */
+ public static String getSpace(Map m1) {
+ Object edgeType = m1.get("edgeType");
+ Object tag = m1.get("tag");
+ String entityTypeName = edgeType != null ? edgeType.toString()
+ : tag != null ? tag.toString()
+ : null;
+
+ String defaultSpace = ENV.getSpace();
+ if (entityTypeName == null) {
+ return defaultSpace;
+ }
+
+ // 获取表名与实体类的映射
+ Map> entityTypeMapping = ENV.getMapperContext().getTagTypeMapping();
+ // 获取实体类
+ Class> entityType = entityTypeMapping.get(entityTypeName);
+ String space = SpaceRouter.spaceFromConfig(entityType);
+ if (isNotBlank(space)) {
+ // 已经是解析后的space
+ return space;
+ }
+ return ENV.getSpace();
+ }
+
+ /**
+ * 通过实体类获取对应的space。 支持占位符,并从配置信息中读取。
+ *
+ * @param entityType 实体类
+ * @return space
+ */
+ public static String spaceFromConfig(Class> entityType) {
+ return spaceFromConfig(entityType, ENV.getContext());
+ }
+
+ /**
+ * 调用时机:在环境启动时,尚获得 context 时调用
+ *
+ * @param entityType 实体类
+ * @param context Spring 上下文
+ * @return space 空间名,已经解析占位符
+ */
+ public static String spaceFromConfig(Class> entityType, ApplicationContext context) {
+ String space = null;
+ ClassModel cm = ENV.getMapperContext().computeEntityClassModelMap().get(entityType);
+ if (cm != null) {
+ space = cm.getSpace();
+ }
+ if (isBlank(space)) {
+ space = spaceFromEntity(entityType, context);
+ }
+ return space;
+ }
+
+ /**
+ * 利用Spring Environment 解析注解的值,用于 @Space 的 name 属性解析
+ *
+ * @param value 需要解析的值,可能是带占位符的 ${xx.xx} ,也可以是固定的字符串
+ * @return resolveResult 解析结果
+ * @throws IllegalArgumentException 当配置了 ${xx.xx} 占位符,且spring配置文件中未指定该配置时抛出
+ * @author Charle004
+ */
+ public static String tryResolvePlaceholder(String value) {
+ return tryResolvePlaceholder(value, ENV.getContext());
+ }
+
+ /**
+ * 利用Spring Environment 解析注解的值,用于 @Space 的 name 属性解析
+ *
+ * @param configKey 需要解析的值,可能是带占位符的 ${xx.xx} ,也可以是固定的字符串
+ * @return resolveResult 解析结果
+ * @throws IllegalArgumentException 当配置了 ${xx.xx} 占位符,且spring配置文件中未指定该配置时抛出
+ * @author Charle004
+ */
+ public static String tryResolvePlaceholder(String configKey, ApplicationContext context) {
+ if (isBlank(configKey)) {
+ return null;
+ }
+ String resolveResult = configKey;
+ if (null != context) {
+ try {
+ resolveResult = context.getEnvironment().resolveRequiredPlaceholders(configKey);
+ } catch (IllegalArgumentException e) {
+ throw new ResourceLoadException(
+ "name ( " + configKey + " ) missing configurable value"
+ );
+ }
+ }
+ return resolveResult;
+ }
+
+}
diff --git a/src/main/java/org/nebula/contrib/ngbatis/utils/ReflectUtil.java b/src/main/java/org/nebula/contrib/ngbatis/utils/ReflectUtil.java
index 667bdeb..6e0687b 100644
--- a/src/main/java/org/nebula/contrib/ngbatis/utils/ReflectUtil.java
+++ b/src/main/java/org/nebula/contrib/ngbatis/utils/ReflectUtil.java
@@ -25,7 +25,6 @@
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Transient;
-import org.nebula.contrib.ngbatis.annotations.Space;
import org.nebula.contrib.ngbatis.annotations.base.EdgeType;
import org.nebula.contrib.ngbatis.annotations.base.Tag;
import org.nebula.contrib.ngbatis.exception.ParseException;
@@ -552,17 +551,29 @@ public static Class> typeArg(Object o, Class> parent, int i) {
Assert.isTrue(o != null, "instance can not be null");
Class> insClass = o.getClass();
if (parent.isInterface()) {
- Type[] interfaces = insClass.getGenericInterfaces();
- for (Type anInterface : interfaces) {
- boolean isType = anInterface instanceof ParameterizedType;
- if (isType) {
- ParameterizedType paramTypeInterface = (ParameterizedType) anInterface;
- boolean found = paramTypeInterface.getRawType() == parent;
- if (found) {
- Type[] actualTypeArguments = paramTypeInterface.getActualTypeArguments();
- boolean noOut = actualTypeArguments.length > i;
- return noOut ? (Class>)actualTypeArguments[i] : null;
- }
+ return typeArg(insClass, parent, i);
+ }
+ return null;
+ }
+
+ /**
+ * 从类型中,获取父类或接口中的泛型参数。
+ * @param clazz 类型
+ * @param parent 所继承的父类或实现的接口
+ * @param i 泛型参数所处下标
+ * @return 泛型
+ */
+ public static Class> typeArg(Class> clazz, Class> parent, int i) {
+ Type[] interfaces = clazz.getGenericInterfaces();
+ for (Type anInterface : interfaces) {
+ boolean isType = anInterface instanceof ParameterizedType;
+ if (isType) {
+ ParameterizedType paramTypeInterface = (ParameterizedType) anInterface;
+ boolean found = paramTypeInterface.getRawType() == parent;
+ if (found) {
+ Type[] actualTypeArguments = paramTypeInterface.getActualTypeArguments();
+ boolean noOut = actualTypeArguments.length > i;
+ return noOut ? (Class>)actualTypeArguments[i] : null;
}
}
}
@@ -620,25 +631,5 @@ public static boolean isGraphId(Field field) {
}
return false;
}
-
- /**
- * 从实体类获取 space,并解析占位符
- */
- public static String spaceFromEntity(Class> entityType) {
- boolean hasSpace = entityType.isAnnotationPresent(Space.class);
- String space = null;
- if (hasSpace) {
- Space spaceAnnotation = entityType.getAnnotation(Space.class);
- space = spaceAnnotation.name();
- }
-
- boolean hasTable = entityType.isAnnotationPresent(Table.class);
- if (hasTable) {
- Table tableAnnotation = entityType.getAnnotation(Table.class);
- space = tableAnnotation.schema();
- }
-
- return space;
- }
}