Compare commits

...

7 Commits

Author SHA1 Message Date
Michael Yang
3c26f72df8 chore: code format 2025-09-25 19:29:37 +08:00
Michael Yang
3618f70055
Merge pull request #587 from ruansheng8/fix-relationQueryNullValue
feat: -m core 优化关联查询使用逗号分割逻辑
2025-09-25 19:23:03 +08:00
Michael Yang
c7bc207ce7
Merge pull request #589 from ruansheng8/fix-relationTableQuery
fix: -m core 修复自动关联表信息查找逻辑
2025-09-25 19:22:20 +08:00
Michael Yang
ec768d2423 docs: update doc 2025-09-25 19:13:39 +08:00
Michael Yang
bf05d11d8e feat: 添加 Assert 方便在执行 update 的时候进行断言 2025-09-25 19:13:07 +08:00
ruansheng
2e5bde372f fix: -m core 修复自动关联查询功能:表信息查找根据Schema+表名 2025-09-25 17:07:54 +08:00
ruansheng
01ab3023df feat: -m core 优化关联查询使用逗号分割时排除空值 2025-09-23 19:59:30 +08:00
5 changed files with 139 additions and 3 deletions

View File

@ -74,7 +74,7 @@ public class Account {
用于监听 Entity 实体类数据被新增到数据库,我们可以在实体类被新增时做一些前置操作。比如:
- 数据填充。
- 默认数据填充:比如插入时间、创建人等等
- 数据修改。
示例代码如下:
@ -109,7 +109,9 @@ public class MyInsertListener implements InsertListener {
## onUpdate
使用方式同 onInsert 一致,用于在数据被更新的时候,设置一些默认数据。
使用方式同 onInsert 一致,用于在数据被更新的时候,设置一些默认数据,比如:更新时间、更新人等等。
也可以用于当前数据的 “权限检查”,比如:更新的数据的用户 id 不是当前登录的用户,则抛出异常,不允许更新等等。
## onSet
@ -121,6 +123,7 @@ onSet 可以用于配置:查询数据 entity (或者 entity 列表、分页
- 场景3一对多一对一查询entity 中定义关联实体,在监听到字段赋值时,主动去查询关联表赋值。
- 场景4字段加密监听到内容被赋值时对内容进行加密处理。
- 场景5字段脱敏出字段内容进行脱敏处理
- 场景6数据验证比如当前用户查询的数据中当前用户没有权限查看则抛出异常等。
示例代码如下:

View File

@ -0,0 +1,107 @@
package com.mybatisflex.core.query;
import com.mybatisflex.core.util.StringUtil;
public class Assert {
private Assert() {
}
/**
* 断言表达式为 true
*
* @param <T> 要返回的值类型
* @param value 要返回的值
* @param expression 断言表达式
* @return 原始值
* @throws IllegalArgumentException 当表达式为 false 时抛出
*/
public static <T> T that(T value, boolean expression) {
if (!expression) {
throw new IllegalArgumentException("Assertion failed");
}
return value;
}
/**
* 断言表达式为 true成功返回指定的值
*
* @param <T> 要返回的值类型
* @param value 要返回的值
* @param expression 断言表达式
* @param message 异常消息
* @return 原始值
* @throws IllegalArgumentException 当表达式为 false 时抛出
*/
public static <T> T that(T value, boolean expression, String message) {
if (!expression) {
throw new IllegalArgumentException(message != null ? message : "Assertion failed");
}
return value;
}
/**
* 断言字符串不为空白延迟计算异常消息
*
* @param text 要验证的字符串
* @param message 异常消息
* @return 原始字符串
* @throws IllegalArgumentException 当字符串为空白时抛出
*/
public static String hasText(String text, String message) {
if (StringUtil.noText(text)) {
throw new IllegalArgumentException(
StringUtil.hasText(message) ? message : "value must have text"
);
}
return text;
}
/**
* 断言字符串不为空白
*
* @param text 要验证的参数
* @return 原始字符串
* @throws IllegalArgumentException 当字符串为空白时抛出
*/
public static boolean hasText(String text) {
if (StringUtil.noText(text)) {
throw new IllegalArgumentException("value must have text");
}
return true;
}
/**
* 断言对象不为空
*
* @param obj 要验证的参数
* @return 原始对象
* @throws IllegalArgumentException 当对象为空时抛出
*/
public static boolean notNull(Object obj) {
if (obj == null) {
throw new IllegalArgumentException("value must not be null");
}
return true;
}
/**
* 断言对象不为空
*
* @param obj 要验证的参数
* @param message 异常消息
* @return 原始对象
* @throws IllegalArgumentException 当对象为空时抛出
*/
public static boolean notNull(Object obj, String message) {
if (obj == null) {
throw new IllegalArgumentException(StringUtil.hasText(message) ? message : "value must not be null");
}
return true;
}
}

View File

@ -86,8 +86,9 @@ public abstract class AbstractRelation<SelfEntity> {
this.selfField = ClassUtil.getFirstField(entityClass, field -> field.getName().equalsIgnoreCase(selfField));
this.selfFieldWrapper = FieldWrapper.of(entityClass, selfField);
String tableNameWithSchema = StringUtil.buildSchemaWithTable(targetSchema, targetTable);
//以使用者注解配置为主
this.targetTableInfo = StringUtil.noText(targetTable) ? TableInfoFactory.ofEntityClass(relationFieldWrapper.getMappingType()) : TableInfoFactory.ofTableName(targetTable);
this.targetTableInfo = StringUtil.noText(targetTable) ? TableInfoFactory.ofEntityClass(relationFieldWrapper.getMappingType()) : TableInfoFactory.ofTableName(tableNameWithSchema);
this.targetSchema = targetTableInfo != null ? targetTableInfo.getSchema() : targetSchema;
this.targetTable = targetTableInfo != null ? targetTableInfo.getTableName() : targetTable;

View File

@ -74,6 +74,10 @@ public class ToManyRelation<SelfEntity> extends AbstractRelation<SelfEntity> {
}
String[] splitValues = ((String) targetValue).split(selfValueSplitBy);
for (String splitValue : splitValues) {
// 排除空值
if (splitValue == null || splitValue.isEmpty()) {
continue;
}
//优化分割后的数据类型(防止在数据库查询时候出现隐式转换)
newTargetValues.add(ConvertUtil.convert(splitValue, targetFieldWrapper.getFieldType()));
}

View File

@ -0,0 +1,21 @@
package com.mybatisflex.coretest;
import com.mybatisflex.core.query.Assert;
import com.mybatisflex.core.query.QueryWrapper;
import org.junit.Test;
import static com.mybatisflex.core.query.QueryMethods.column;
public class AssertTest {
@Test(expected = IllegalArgumentException.class)
public void testAssert() {
String testArg = null;
QueryWrapper queryWrapper = new QueryWrapper()
.from("account")
.where(column("id").eq(1, Assert::notNull))
.and(column("name").eq(testArg, Assert::hasText));
}
}