condition
这种数据来源直接从 DataStore 中获取动态数据(可以简单理解为从 DB 中获取数据)。通过配置 condition ,可以指定数据获取的 where 条件。
如:“condition”: “type == ‘Server’” 表示条件为模型字段为type,值为Server。
Condition 语法
目前支持特性:
- 字符串:‘string’ 、“string”
- 数字:1 、1.1
- 变量:以英文字母开头的由英文、数字和下划线组成的连续字串
- null :null
- 括号:()
- 数组:[]
- 逻辑与和逻辑或:&& 、||
- 单值比较运算:== 、!= 、> 、>= 、< 、<=
- 数组比较运算:in 、!in
- 字符串模糊匹配:contains
- 动态推断比较运算:match
- 下级字段:. ,例如 owner.name ,可连续多级
- 内置变量:$currentUser 获取当前登陆用户 id
举例:
(a == 1 || b == 2) && (c == 3 || d == 4)a > 1 && b >= 2 && c < 3 && d <= 4 && e == 5 && f != 6a in [1, 2, 3] && b !in ['a', 'b', 'c'] && c in [var1, var2, 'string']name contains 'Ive'a match a && b match bowner.name match namea == null && b != nulluser == $currentUsercompany == $context.companyId
同时有几个限制:
- 目前不支持取反操作,也就是类似 !(b < 2) 这样的逻辑是不支持的。
- 目前也同样不支持比较运算的嵌套,也就是将一个比较运算作为另一个比较运算的右操作数,例如 a == (b > 2) 。
- 比较运算左操作数只能是被查询模型的字段名,不允许是数字或字符串,也不能和右操作数左右互换。
- match 的右操作数只能是变量,不可为常量。
match 比较
match 比较特别,是为了方便泛化使用条件表达式而专门强化的一个运算符,取决于传入的参数不同而不同。分别对应传入单值、集合值和范围值的情况,会分别被解析为被解析为 == value 、in values 、 >= value_start && <= value_end 。在大多数对变量的比较中,都可以直接使用 match ,Trantor 会自动进行处理。
关联模型比较
Trantor 的模型中的字段,可以是一个关联模型,对这种类型的字段进行比较时,默认使用 id 来比较。例如 owner == 1 实际上会被识别为类似 owner.id == 1 ,或者说按 GQL 的方式理解的话就是:
{"owner": { "id": 1}}同样也支持 > 、< 和 in 、match 等其他的比较操作。
非 id 字段则需要显式指定:owner.name contains ‘username’ 。
查询值为空时忽略
目前条件表达式解析时,如果遇到右操作数对应的查询不存在时,整个条件分支会被丢弃,以便使一个查询条件表达式适用更多场景。举例 a > 1 && b == b 时,如果 queryValues 中 b 不存在,则实际为被执行的只有 a > 1 。
如果确实需要做空判断,需要在 queryValues 中传入一个确实的空值 {type: ‘One’, value: null}
自定义变量
当内置变量无法满足需求,查询需要带上业务相关的条件时,如当前公司 id ,可以使用此功能。
1:实现 ConditionHandler 中的 handler() 方法,并注册为 spring bean
public interface ConditionHandler { interface HandlerConsumer { void accept(TConditionContext context, ServletRequest request, ServletResponse response); }
HandlerConsumer handler();}@Componentpublic class TestConditionHandler implements ConditionHandler { @Override public HandlerConsumer handler() { return (context, request, response) -> context.addVariable("companyId", 1); }}2:在 condition 中配置自定义变量
company == $context.companyId
注意
- 如果该变量需要在别的模块复用,可以把添加变量的逻辑加入 api jar 中,在别的模块中引用即可。
- 目前仅支持一级,即只能 . 一层
Condition 为空的默认推断行为
- 当所属模型和入参模型相同
1:如果入参包含 id ,则 condition 默认为 id match id 。
2:如果入参不包含 id ,则 condition 默认为所有入参字段进行匹配,例如入参中包含 name 和 age ,则理解为 name match name && age match age 。
- 当所属模型和目标模型不同
1:如果入参是单条数据条目,默认寻找第一个 relation 字段用作查询条件。
2:如果入参是多条数据条目,默认寻找第一个 relation 字段用作查询条件,按 IN 方式处理。
示例
示例一:
获取未冻结的学生信息 condition:“status != Frozen” 对应模型定义片段:
@TModelclass Student extends BaseModel<Long> { // some other fields @TModelField private Status status;}
enum Status { Normal, Frozen,}示例二:
使用入参商品的 id 查询对应的订单 condition:item == id 对应模型定义片段(等同于item.id == id,不写默认是等同模型中相同的参数):
@TModelclass Order extends BaseModel<Long> { // some other fields @TModelField @RelationMeta(name = "OrderItem") private Item item;}
@TModelclass Item extends BaseModel<Long> { // item fields}示例三:
找出当前用户的,按固定时间段过滤的订单(时间段来自于 Form 提交) condition:buyer == $currentUser && createdAt match createdAt 对应模型定义片段:
@TModel class Order extends BaseModel<Long> { // some other fields @TModelField @RelationMeta(name = "OrderBuyer") private User buyer; }`注:
- createdAt 字段定义在 BaseModel 中
- createdAt match createdAt 的含义是目标模型中的 createdAt 字段匹配 Action 入参中的 createdAt 参数;其中 createdAt 参数由前一个视图的 Form 数据容器提供,在 Form 中 Date 类型字段会被渲染成一个时间段选择器,因此给出的结果其实是一个
Range<Date>;match 会适配不同的参数结构,进行不同的匹配,对于 Range 则等同于createdAt >= createdAt_start && createdAt <= createdAt_end