Skip to content

Commit

Permalink
Merge pull request #295 from CorvusYe/master
Browse files Browse the repository at this point in the history
  • Loading branch information
wey-gu authored May 5, 2024
2 parents 4058ee1 + 7fb441f commit e8504c0
Show file tree
Hide file tree
Showing 13 changed files with 201 additions and 68 deletions.
14 changes: 11 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,25 @@ This source code is licensed under Apache 2.0 License.

- [x] Springboot 3.x support. (lastest-jdk17)

# NEXT (1.2.2-SNAPSHOT)
# 1.2.2

## Bugfix

- fix: complete the error code of ResultSet into QueryException.
- fix: the issue of not being able to handle Set type.
- fix: the issue of the ranking value of the edge object cannot be filled.
- fix: when the field is aliased by `@Column`, the param name is incorrect. (multi tags support)
- selectBySelective
- selectIdBySelective
- selectBySelectiveStringLike
- selectIdBySelectiveStringLike
- fix: unable to read the correct value of id, the value of the subclass' id is used now. (multi tag scene)
- fix: do not generate asg debug when the log level is not debug, now.

## Dependencies upgrade
## Develop behavior change

- [ ] nebula-java: 3.6.0 -> 3.6.1
- No longer verifying the number of `@Id` in the entity, please keep the number to 1 on your own.
> 不再对实体中的`@Id`个数进行校验,请注意保持个数为1 (含父类)
# 1.2.1

Expand Down
11 changes: 6 additions & 5 deletions README-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,21 @@ Copyright (c) 2022 All project authors and nebula-contrib. All rights reserved.
This source code is licensed under Apache 2.0 License.
-->

# NGBATIS
# NgBatis

<p align="center">
<br> <a href="README.md">English</a> | 中文
</p>

- [Ngbatis Docs](https://nebula-contrib.github.io/ngbatis/)
- [Ngbatis 文档](https://graph-cn.github.io/ngbatis-docs/)
- [NgBatis Docs](https://nebula-contrib.github.io/ngbatis/)
- [NgBatis 文档](https://graph-cn.github.io/ngbatis-docs/)

## NGBATIS是什么?

**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)的单表操作,另外还有一些图特有的实体-关系基本操作。
**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)的单表操作,另外还有一些图特有的实体-关系基本操作。
如果使用上更习惯于JPA的方式,[graph-ocean](https://github.com/nebula-contrib/graph-ocean) 是个不错的选择。

## NGBATIS 是怎么运行的?
## NgBatis 是怎么运行的?

请看设计文档 [EXECUTION-PROCESS.md](./EXECUTION-PROCESS.md)

Expand All @@ -33,6 +33,7 @@ This source code is licensed under Apache 2.0 License.

NgBatis | nebula-java | JDK | Springboot | Beetl
---|-------------|---|------------|---
1.2.2 | 3.6.0 | 8 | 2.7.0 | 3.15.10.RELEASE
1.2.1-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
1.2.0-jdk17 | 3.6.0 | 17 | 3.0.7 | 3.15.10.RELEASE
Expand Down
11 changes: 6 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,18 @@ Copyright (c) 2022 All project authors and nebula-contrib. All rights reserved.
This source code is licensed under Apache 2.0 License.
-->

# NGBATIS
# NgBatis

<p align="center">
<br> English | <a href="README-CN.md">中文</a>
</p>

- [Ngbatis Docs](https://nebula-contrib.github.io/ngbatis/)
- [Ngbatis 文档](https://graph-cn.github.io/ngbatis-docs/)
- [NgBatis Docs](https://nebula-contrib.github.io/ngbatis/)
- [NgBatis 文档](https://graph-cn.github.io/ngbatis-docs/)

## What is NGBATIS
## What is NgBatis

**NGBATIS** is a database ORM framework base [NebulaGraph](https://github.com/vesoft-inc/nebula) + spring-boot, which takes advantage of the [mybatis’](https://github.com/mybatis/mybatis-3) fashion development, including some de-factor operations in single table and vertex-edge, like [mybatis-plus](https://github.com/baomidou/mybatis-plus).
**NgBatis** is a database ORM framework base [NebulaGraph](https://github.com/vesoft-inc/nebula) + spring-boot, which takes advantage of the [mybatis’](https://github.com/mybatis/mybatis-3) fashion development, including some de-factor operations in single table and vertex-edge, like [mybatis-plus](https://github.com/baomidou/mybatis-plus).

If you prefer JPA, [graph-ocean](https://github.com/nebula-contrib/graph-ocean) is a good choice.

Expand All @@ -34,6 +34,7 @@ See [EXECUTION-PROCESS.md](./EXECUTION-PROCESS.md)

NgBatis | nebula-java | JDK | Springboot | Beetl
---|-------------|---|------------|---
1.2.2 | 3.6.0 | 8 | 2.7.0 | 3.15.10.RELEASE
1.2.1-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
1.2.0-jdk17 | 3.6.0 | 17 | 3.0.7 | 3.15.10.RELEASE
Expand Down
2 changes: 1 addition & 1 deletion ngbatis-demo/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
<dependency>
<groupId>org.nebula-contrib</groupId>
<artifactId>ngbatis</artifactId>
<version>1.2.2-SNAPSHOT</version>
<version>1.2.2</version>
</dependency>
</dependencies>

Expand Down
13 changes: 8 additions & 5 deletions ngbatis-demo/src/main/resources/testgraph.ngql
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
create space if not exists test (vid_type = fixed_string(32))
:sleep 20
use test
create tag if not exists person(name string,gender string,height double,age int32 ,birthday datetime)
create tag if not exists employee(name string,gender string,height double,age int32 ,birthday datetime,position string)
create edge if not exists like(likeness double)
create tag index person_index_1 on person(age,birthday)
use test;
create tag if not exists person(name string,gender string,height double,age int32 ,birthday datetime);
create tag if not exists employee(name string,gender string,height double,age int32 ,birthday datetime,position string);
create edge if not exists like(likeness double);
create tag index person_index_1 on person(age,birthday);

CREATE tag `column_alias` (`first_name` string NULL , `last_name` string NULL );
CREATE TAG INDEX `i_column_alias_first_name` ON `column_alias`(`first_name`(50));
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@
//
// This source code is licensed under Apache 2.0 License.

import java.util.List;
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;
Expand All @@ -16,26 +20,97 @@
* <br>Now is history!
*/
@SpringBootTest
@TestMethodOrder(OrderAnnotation.class)
public class ColumnAliasDaoTest {

@Autowired
private ColumnAliasDao dao;
static final String idNo = "ID" + System.currentTimeMillis();
static final String firstName = Math.random() + "";

@Test
public void updateById() {
long now = System.currentTimeMillis();
String idNo = "UBI" + now;
@Order(1)
public void insert() {
ColumnAlias colAliasPojo = new ColumnAlias();
colAliasPojo.setIdNo(idNo);
dao.insert(colAliasPojo);
}

String firstName = Math.random() + "";
@Test
@Order(2)
public void updateById() {
ColumnAlias colAliasPojo = new ColumnAlias();
colAliasPojo.setIdNo(idNo);
colAliasPojo.setFirstName(firstName);
dao.updateById(colAliasPojo);

}

@Test
@Order(3)
public void selectById() {
ColumnAlias colAliasPojoDb = dao.selectById(idNo);

Assert.isTrue(firstName.equals(colAliasPojoDb.getFirstName()));
Assert.isTrue(idNo.equals(colAliasPojoDb.getIdNo()));
}

@Test
@Order(4)
public void selectBySelective() {
ColumnAlias colAliasPojo = new ColumnAlias();
colAliasPojo.setIdNo(idNo);
colAliasPojo.setFirstName(firstName);
List<ColumnAlias> nodesInDb = dao.selectBySelective(colAliasPojo);
Assert.isTrue(nodesInDb.size() > 0);
nodesInDb.forEach(node -> {
Assert.isTrue(node.getFirstName().equals(firstName));
Assert.isTrue(node.getIdNo().equals(idNo));
});
}

@Test
@Order(5)
public void selectIdBySelective() {
ColumnAlias colAliasPojo = new ColumnAlias();
colAliasPojo.setIdNo(idNo);
colAliasPojo.setFirstName(firstName);
List<String> idsInDb = dao.selectIdBySelective(colAliasPojo);
Assert.isTrue(idsInDb.contains(idNo));
}

@Test
@Order(6)
public void selectBySelectiveStringLike() {
ColumnAlias colAliasPojo = new ColumnAlias();
String query = firstName.substring(0, 5);
colAliasPojo.setFirstName(query);
List<ColumnAlias> nodesInDb = dao.selectBySelectiveStringLike(colAliasPojo);
Assert.isTrue(nodesInDb.size() > 0);
nodesInDb.forEach(node -> Assert.isTrue(node.getFirstName().contains(query)));
}

// selectIdBySelectiveStringLike
@Test
@Order(7)
public void selectIdBySelectiveStringLike() {
ColumnAlias colAliasPojo = new ColumnAlias();
colAliasPojo.setIdNo(idNo);
String query = firstName.substring(0, 5);
colAliasPojo.setFirstName(query);
List<String> idsInDb = dao.selectIdBySelectiveStringLike(colAliasPojo);
Assert.isTrue(idsInDb.contains(idNo));
}

@Test
@Order(99)
public void deleteById() {
dao.deleteById(idNo);
}

@Test
@Order(100)
public void selectByIdAfterDelete() {
ColumnAlias colAliasPojoDb = dao.selectById(idNo);
Assert.isTrue(colAliasPojoDb == null);
}

}
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<name>ngbatis</name>
<groupId>org.nebula-contrib</groupId>
<artifactId>ngbatis</artifactId>
<version>1.2.2-SNAPSHOT</version>
<version>1.2.2</version>

<description>
NgBatis is a database ORM framework base NebulaGraph + spring-boot,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
//
// This source code is licensed under Apache 2.0 License.

import static org.nebula.contrib.ngbatis.utils.ReflectUtil.getAllColumnFields;
import static org.nebula.contrib.ngbatis.utils.ReflectUtil.isCurrentTypeOrParentType;
import static org.nebula.contrib.ngbatis.utils.ReflectUtil.typeArg;

Expand Down Expand Up @@ -132,8 +133,8 @@ public void init() {
put(Object.class, (Setter<Object>) (obj) -> {
Map<String, Object> pojoFields = new HashMap<>();
Class<?> paramType = obj.getClass();
Field[] declaredFields = paramType.getDeclaredFields();
for (Field declaredField : declaredFields) {
Field[] allFields = getAllColumnFields(paramType);
for (Field declaredField : allFields) {
Object nebulaValue = toNebulaValueType(
ReflectUtil.getValue(obj, declaredField),
declaredField
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,10 @@ public KV recordToKV(Object record, Iterable<Field> fields, boolean selective, S
List<String> currentTagColumns = kv.multiTagColumns
.computeIfAbsent(tagName, (k) -> new ArrayList<>());
currentTagColumns.add(name);

List<String> currentTagFields = kv.multiTagFields
.computeIfAbsent(tagName, (k) -> new ArrayList<>());
currentTagFields.add(field.getName());

kv.columns.add(name);
Object[] paras = {value};
Expand Down Expand Up @@ -139,7 +143,11 @@ private void initFieldGroups(Object record, KV kv) {
}

public static class KV {
// 以 tagName 为 key,列名列表为 value
// 使用 LinkedHashMap 保证顺序,使得推入字段的顺序与 columns、values、types 一致
public final Map<String, List<String>> multiTagColumns = new LinkedHashMap<>();
// 以 tagName 为 key,属性名列表为 value
public final Map<String, List<String>> multiTagFields = new LinkedHashMap<>();
public final List<String> columns = new ArrayList<>();
public final List<String> valueNames = new ArrayList<>();
public final List<Object> values = new ArrayList<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* 基于 ASM 对接口进行动态代理,并生成 Bean 代理的实现类
Expand All @@ -25,6 +27,8 @@
* <br>Now is history!
*/
public class MapperProxyClassGenerator implements Opcodes {

private final Logger log = LoggerFactory.getLogger(MapperProxyClassGenerator.class);

/**
* 获取DAO接口对应的动态代理类名称
Expand Down Expand Up @@ -74,7 +78,9 @@ public byte[] setClassCode(ClassModel cm) {
byte[] code = cw.toByteArray();
cm.setClassByte(code);

writeFile(cm);
if (log.isDebugEnabled()) {
writeFile(cm);
}

return code;
}
Expand Down
13 changes: 11 additions & 2 deletions src/main/java/org/nebula/contrib/ngbatis/utils/ReflectUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ public static Set<Class<?>> getParentTypes(Class<?> paramType) {
* 实体类获取全部属性,对父类获取 带 @Column 的属性
*
* @param clazz 实体类
* @return 当前类的属性及其父类中,带@Column注解的属性
* @return 当前类及其父类的属性,排除 {@link Transient} 注解的属性
*/
public static Field[] getAllColumnFields(Class<?> clazz) {
return getAllColumnFields(clazz, false);
Expand All @@ -334,7 +334,8 @@ public static Field[] getAllColumnFields(Class<?> clazz) {
*
* @param clazz 实体类
* @param forValueSetting 用于设值时为 true,读取全属性
* @return 当前类的属性及其父类中,带@Column注解的属性
* 否则只过滤{@link Transient}注解的属性
* @return 当前类及其父类的属性
*/
public static Field[] getAllColumnFields(Class<?> clazz, boolean forValueSetting) {
Set<Field> fields = new LinkedHashSet<>();
Expand Down Expand Up @@ -413,11 +414,19 @@ public static Field getPkField(Field[] fields, Class<?> type) {
*/
public static Field getPkField(Field[] fields, Class<?> type, boolean canNotNull) {
Field pkField = null;
Field typePkField = null;
for (Field field : fields) {
if (field.isAnnotationPresent(Id.class)) {
pkField = field;
if (field.getDeclaringClass().equals(type)) {
typePkField = field;
}
}
}
// 多标签时,以运行时类中的 @Id 注解为准
if (typePkField != null) {
pkField = typePkField;
}
if (canNotNull && pkField == null) {
throw new ParseException(
String.format("%s 必须有一个属性用 @Id 注解。(javax.persistence.Id)", type));
Expand Down
23 changes: 15 additions & 8 deletions src/main/java/org/nebula/contrib/ngbatis/utils/ResultSetUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -344,10 +344,15 @@ public static void relationshipToResultType(Object o, String fieldName,
*/
public static void setId(Object obj, Class<?> resultType, Node v)
throws IllegalAccessException {
Field pkField = getPkField(resultType);
ValueWrapper idWrapper = v.getId();
Object id = ResultSetUtil.getValue(idWrapper);
ReflectUtil.setValue(obj, pkField, id);
Field pkField = getPkField(resultType, false);
if (pkField != null) {
ValueWrapper idWrapper = v.getId();
Object id = ResultSetUtil.getValue(idWrapper);
ReflectUtil.setValue(obj, pkField, id);
}
if (resultType.getSuperclass() != null) {
setId(obj, resultType.getSuperclass(), v);
}
}

/**
Expand All @@ -362,11 +367,13 @@ public static void setId(Object obj, Class<?> resultType, Node v)
public static void setRanking(Object obj, Class<?> resultType, Relationship e)
throws IllegalAccessException {
Field pkField = getPkField(resultType, false);
if (pkField == null) {
return;
if (pkField != null) {
long ranking = e.ranking();
ReflectUtil.setValue(obj, pkField, ranking);
}
if (resultType.getSuperclass() != null) {
setRanking(obj, resultType.getSuperclass(), e);
}
long ranking = e.ranking();
ReflectUtil.setValue(obj, pkField, ranking);
}

/**
Expand Down
Loading

0 comments on commit e8504c0

Please sign in to comment.