From 9cfac27775b6cd03042c05650b2914ebd8fb66c4 Mon Sep 17 00:00:00 2001 From: CorvusYe Date: Fri, 19 Jul 2024 17:38:03 +0800 Subject: [PATCH 1/2] feat: support adding ID attributes of start and end nodes in edge entities. --- CHANGELOG.md | 4 +- .../ye/weicheng/ngbatis/demo/pojo/Like.java | 12 ++++++ .../contrib/ngbatis/annotations/DstId.java | 24 ++++++++++++ .../contrib/ngbatis/annotations/SrcId.java | 24 ++++++++++++ .../ngbatis/binding/beetl/functions/KvFn.java | 7 ++++ .../contrib/ngbatis/proxy/MapperProxy.java | 1 - .../contrib/ngbatis/utils/ReflectUtil.java | 39 +++++++++++++------ .../contrib/ngbatis/utils/ResultSetUtil.java | 30 +++++++++++++- 8 files changed, 127 insertions(+), 14 deletions(-) create mode 100644 src/main/java/org/nebula/contrib/ngbatis/annotations/DstId.java create mode 100644 src/main/java/org/nebula/contrib/ngbatis/annotations/SrcId.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e6b8dda..1c022a39 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,7 +32,7 @@ This source code is licensed under Apache 2.0 License. - nebula-java: 3.6.0 -> 3.8.3 - org.hibernate:hibernate-core was excluded. -> If you need to use hibernate-core, please add the dependency by yourself. + > If you need to use hibernate-core, please add the dependency by yourself. ## Bugfix @@ -48,6 +48,8 @@ This source code is licensed under Apache 2.0 License. - feat: support ssl and http2 config in yml. > http2 属于企业版的数据库才支持,但我没有测试环境,所以不确定是否可用。 > http2 is supported by the enterprise version of the database, but I don't have a test environment, so I'm not sure if it works. +- feat: support adding ID attributes of start and end nodes in edge entities. + > 通过 @DstId, @SrcId 进行注解,可以将属性标记成特殊的属性,用于查询时可以填充的起始点和终点的id值。 - example: diff --git a/ngbatis-demo/src/main/java/ye/weicheng/ngbatis/demo/pojo/Like.java b/ngbatis-demo/src/main/java/ye/weicheng/ngbatis/demo/pojo/Like.java index 16d5e52c..65bd918a 100644 --- a/ngbatis-demo/src/main/java/ye/weicheng/ngbatis/demo/pojo/Like.java +++ b/ngbatis-demo/src/main/java/ye/weicheng/ngbatis/demo/pojo/Like.java @@ -4,7 +4,10 @@ // // This source code is licensed under Apache 2.0 License. +import javax.persistence.Id; import javax.persistence.Table; +import org.nebula.contrib.ngbatis.annotations.DstId; +import org.nebula.contrib.ngbatis.annotations.SrcId; /** *

关系实体类示例。

@@ -15,6 +18,15 @@ @Table(name = "like") public class Like { + @Id // 可选,如果两个节点之间同一类型边的唯一性由源节点id和目标节点id共同决定,可以不加当前属性 + private Long rank; + + @SrcId // 可选,如果不需要获取关系的源节点id,可以不加当前属性 + private String srcId; + + @DstId // 可选,如果不需要获取关系的目标节点id,可以不加当前属性 + private String dstId; + private Double likeness; public Double getLikeness() { diff --git a/src/main/java/org/nebula/contrib/ngbatis/annotations/DstId.java b/src/main/java/org/nebula/contrib/ngbatis/annotations/DstId.java new file mode 100644 index 00000000..9dbcdc99 --- /dev/null +++ b/src/main/java/org/nebula/contrib/ngbatis/annotations/DstId.java @@ -0,0 +1,24 @@ +package org.nebula.contrib.ngbatis.annotations; + +// Copyright (c) 2024 All project authors. All rights reserved. +// +// This source code is licensed under Apache 2.0 License. + +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +/** + * 用于标记目标ID的注解。 + * + * @author yeweicheng + * @since 2024-07-18 17:27 + *
Now is history! + */ +@Target(ElementType.FIELD) +@Retention(RUNTIME) +public @interface DstId { + +} diff --git a/src/main/java/org/nebula/contrib/ngbatis/annotations/SrcId.java b/src/main/java/org/nebula/contrib/ngbatis/annotations/SrcId.java new file mode 100644 index 00000000..e8215678 --- /dev/null +++ b/src/main/java/org/nebula/contrib/ngbatis/annotations/SrcId.java @@ -0,0 +1,24 @@ +package org.nebula.contrib.ngbatis.annotations; + +// Copyright (c) 2024 All project authors. All rights reserved. +// +// This source code is licensed under Apache 2.0 License. + +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +/** + * 用于标记源ID的注解。 + * + * @author yeweicheng + * @since 2024-07-18 17:24 + *
Now is history! + */ +@Target(ElementType.FIELD) +@Retention(RUNTIME) +public @interface SrcId { + +} diff --git a/src/main/java/org/nebula/contrib/ngbatis/binding/beetl/functions/KvFn.java b/src/main/java/org/nebula/contrib/ngbatis/binding/beetl/functions/KvFn.java index 84a27191..e5fababa 100644 --- a/src/main/java/org/nebula/contrib/ngbatis/binding/beetl/functions/KvFn.java +++ b/src/main/java/org/nebula/contrib/ngbatis/binding/beetl/functions/KvFn.java @@ -15,6 +15,8 @@ import java.util.List; import java.util.Map; import java.util.Set; +import org.nebula.contrib.ngbatis.annotations.DstId; +import org.nebula.contrib.ngbatis.annotations.SrcId; import org.nebula.contrib.ngbatis.utils.ReflectUtil; /** @@ -51,6 +53,11 @@ public Object call(Object entity, String prefix, Boolean excludePk, Boolean sele if (pkField != null && pkField.equals(field)) { continue; } + + boolean isVidField = field.isAnnotationPresent(SrcId.class) || field.isAnnotationPresent(DstId.class); + if (excludePk && isVidField) { + continue; + } fieldList.add(field); } 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 9175c1bc..e69b5a05 100644 --- a/src/main/java/org/nebula/contrib/ngbatis/proxy/MapperProxy.java +++ b/src/main/java/org/nebula/contrib/ngbatis/proxy/MapperProxy.java @@ -110,7 +110,6 @@ public static Object invoke(MethodModel methodModel, Object... args) { * @return 结果值 */ public static Object invoke(ClassModel classModel, MethodModel methodModel, Object... args) { - Method method = methodModel.getMethod(); ResultSet query = null; // 参数格式转换 final long step0 = System.currentTimeMillis(); 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 0af4cd66..18010964 100644 --- a/src/main/java/org/nebula/contrib/ngbatis/utils/ReflectUtil.java +++ b/src/main/java/org/nebula/contrib/ngbatis/utils/ReflectUtil.java @@ -6,6 +6,7 @@ import static org.springframework.util.ObjectUtils.nullSafeEquals; +import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Type; @@ -413,25 +414,41 @@ public static Field getPkField(Field[] fields, Class type) { * @return 主键属性 */ public static Field getPkField(Field[] fields, Class type, boolean canNotNull) { - Field pkField = null; - Field typePkField = null; + return getAnnoField(fields, type, canNotNull, Id.class); + } + + public static Field getAnnoField(Class type, Class anno) { + Field[] allColumnFields = getAllColumnFields(type); + return getAnnoField(allColumnFields, type, false, anno); + } + + public static Field getAnnoField( + Field[] fields, Class type, boolean canNotNull, + Class anno) { + Field markedField = null; + Field typeMarkedField = null; for (Field field : fields) { - if (field.isAnnotationPresent(Id.class)) { - pkField = field; + if (field.isAnnotationPresent(anno)) { + markedField = field; if (field.getDeclaringClass().equals(type)) { - typePkField = field; + typeMarkedField = field; } } } - // 多标签时,以运行时类中的 @Id 注解为准 - if (typePkField != null) { - pkField = typePkField; + // 多标签时,以运行时类中的注解为准,如 @Id + if (typeMarkedField != null) { + markedField = typeMarkedField; } - if (canNotNull && pkField == null) { + if (canNotNull && markedField == null) { throw new ParseException( - String.format("%s 必须有一个属性用 @Id 注解。(javax.persistence.Id)", type)); + String.format( + "%s 必须有一个属性用 @%s 注解。(%s)", + type, + anno.getSimpleName(), + anno.getName() + )); } - return pkField; + return markedField; } public static Class typeArg(Object o, Class parent, int i) { diff --git a/src/main/java/org/nebula/contrib/ngbatis/utils/ResultSetUtil.java b/src/main/java/org/nebula/contrib/ngbatis/utils/ResultSetUtil.java index 4c78b9c9..57f9699b 100644 --- a/src/main/java/org/nebula/contrib/ngbatis/utils/ResultSetUtil.java +++ b/src/main/java/org/nebula/contrib/ngbatis/utils/ResultSetUtil.java @@ -31,6 +31,8 @@ import java.util.Map; import java.util.Set; import java.util.stream.Collectors; +import org.nebula.contrib.ngbatis.annotations.DstId; +import org.nebula.contrib.ngbatis.annotations.SrcId; import org.nebula.contrib.ngbatis.exception.ResultHandleException; import org.nebula.contrib.ngbatis.models.MapperContext; import org.nebula.contrib.ngbatis.proxy.MapperProxy; @@ -307,7 +309,7 @@ public static T relationshipToResultType(Relationship r, Class resultType for (Map.Entry entry : properties.entrySet()) { ReflectUtil.setValue(t, entry.getKey(), ResultSetUtil.getValue(entry.getValue())); } - setRanking(t, resultType, r); + setEdgeExtraAttrs(t, resultType, r); } catch (UnsupportedEncodingException | InstantiationException | NoSuchFieldException | IllegalAccessException e) { e.printStackTrace(); @@ -366,6 +368,7 @@ public static void setId(Object obj, Class resultType, Node v) * @throws IllegalAccessException 当 ranking 值的类型,与 * e 中的 ranking 值的类型不匹配时报错,当属性被 final 修饰时报错 */ + @Deprecated public static void setRanking(Object obj, Class resultType, Relationship e) throws IllegalAccessException { Field pkField = getPkField(resultType, false); @@ -377,6 +380,31 @@ public static void setRanking(Object obj, Class resultType, Relationship e) setRanking(obj, resultType.getSuperclass(), e); } } + + public static void setEdgeExtraAttrs(Object t, Class resultType, Relationship e) + throws IllegalAccessException { + Field pkField = getPkField(resultType, false); + if (pkField != null) { + long ranking = e.ranking(); + ReflectUtil.setValue(t, pkField, ranking); + } + + Field srcIdField = ReflectUtil.getAnnoField(resultType, SrcId.class); + if (srcIdField != null) { + Object srcId = ResultSetUtil.getValue(e.srcId()); + ReflectUtil.setValue(t, srcIdField, srcId); + } + + Field dstIdField = ReflectUtil.getAnnoField(resultType, DstId.class); + if (dstIdField != null) { + Object dstId = ResultSetUtil.getValue(e.dstId()); + ReflectUtil.setValue(t, dstIdField, dstId); + } + + if (resultType.getSuperclass() != null) { + setEdgeExtraAttrs(t, resultType.getSuperclass(), e); + } + } /** * Set java entity attributes from Node's properties. From 42e1d43a2d6e450d68334e1ce76a0ae356cce1dd Mon Sep 17 00:00:00 2001 From: CorvusYe Date: Thu, 25 Jul 2024 03:28:16 +0800 Subject: [PATCH 2/2] v1.3.0 --- CHANGELOG.md | 2 ++ README-CN.md | 6 ++++-- README.md | 8 ++++---- ngbatis-demo/pom.xml | 2 +- pom.xml | 2 +- 5 files changed, 12 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c022a39..a9fe6e50 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,8 @@ This source code is licensed under Apache 2.0 License. # NEXT +# 1.3.0 + ## Dependencies upgrade - nebula-java: 3.6.0 -> 3.8.3 diff --git a/README-CN.md b/README-CN.md index 33b7264c..81c144f1 100644 --- a/README-CN.md +++ b/README-CN.md @@ -33,6 +33,8 @@ This source code is licensed under Apache 2.0 License. NgBatis | nebula-java | JDK | Springboot | Beetl ---|-------------|---|------------|--- + 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 1.2.2-jdk17 | 3.6.0 | 17 | 3.0.7 | 3.15.10.RELEASE 1.2.1 | 3.6.0 | 8 | 2.7.0 | 3.15.10.RELEASE @@ -62,14 +64,14 @@ This source code is licensed under Apache 2.0 License. org.nebula-contrib ngbatis - 1.2.2 + 1.3.0 ``` - Gradle ```groovy - implementation 'org.nebula-contrib:ngbatis:1.2.2' + implementation 'org.nebula-contrib:ngbatis:1.3.0' ``` ### 参考 [【ngbatis-demo】](./ngbatis-demo),与springboot无缝集成。在该项目的 test 中还有api的样例。在开发过程中每增加一个特性也都会同步更新ngbatis-demo的用例 diff --git a/README.md b/README.md index f3840fe9..31898a62 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,8 @@ See [EXECUTION-PROCESS.md](./EXECUTION-PROCESS.md) NgBatis | nebula-java | JDK | Springboot | Beetl ---|-------------|---|------------|--- + 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 1.2.2-jdk17 | 3.6.0 | 17 | 3.0.7 | 3.15.10.RELEASE 1.2.1 | 3.6.0 | 8 | 2.7.0 | 3.15.10.RELEASE @@ -41,8 +43,6 @@ See [EXECUTION-PROCESS.md](./EXECUTION-PROCESS.md) 1.2.0 | 3.6.0 | 8 | 2.7.0 | 3.15.10.RELEASE 1.1.5 | 3.5.0 | 8 | 2.7.0 | 3.1.8.RELEASE 1.1.4 | 3.5.0 | 8 | 2.7.0 | 3.1.8.RELEASE - 1.1.3 | 3.5.0 | 8 | 2.7.0 | 3.1.8.RELEASE - 1.1.2 | 3.4.0 | 8 | 2.7.0 | 3.1.8.RELEASE ### SNAPSHOT @@ -64,14 +64,14 @@ See [EXECUTION-PROCESS.md](./EXECUTION-PROCESS.md) org.nebula-contrib ngbatis - 1.2.2 + 1.3.0 ``` - Gradle ```groovy - implementation 'org.nebula-contrib:ngbatis:1.2.2' + implementation 'org.nebula-contrib:ngbatis:1.3.0' ``` - 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. diff --git a/ngbatis-demo/pom.xml b/ngbatis-demo/pom.xml index 2e65f397..098720a6 100644 --- a/ngbatis-demo/pom.xml +++ b/ngbatis-demo/pom.xml @@ -50,7 +50,7 @@ org.nebula-contrib ngbatis - 1.2.3-SNAPSHOT + 1.3.0 diff --git a/pom.xml b/pom.xml index 3a125d18..6f99436a 100644 --- a/pom.xml +++ b/pom.xml @@ -13,7 +13,7 @@ ngbatis org.nebula-contrib ngbatis - 1.2.3-SNAPSHOT + 1.3.0 NgBatis is a database ORM framework base NebulaGraph + spring-boot,