多模型联表查询
- 多对一或者一对一关联关系,通过关联模型的字段查询数据
模型结构定义
模型A
@Model(displayName = "A")
@Model.model(A.MODEL_MODEL)
public class A extends IdModel {
public final static String MODEL_MODEL = "test.A";
@Field(displayName = "b")
@Field.many2one
@Field.Relation(relationFields = {"bId"}, referenceFields = {"id"})
private B b;
@Field(displayName = "bId")
@Field.Integer
private Long bId;
@Field(displayName = "B审批状态")
@Field.Enum
@Field.Related(related = {"b", "approvalEnum"})
private ApprovalEnum approvalEnum;
}
模型B
@Model(displayName = "B")
@Model.model(B.MODEL_MODEL)
public class B extends IdModel {
public final static String MODEL_MODEL = "test.B";
@Field(displayName = "审批状态")
@Field.Enum
private ApprovalEnum approvalEnum;
}
页面设计
在界面设计器中, 设计相对应的表格页面。 A模型related字段拖到搜索栏中。
发布页面
自定义Hook
import cz.jirutka.rsql.parser.ast.RSQLOperators;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.stereotype.Component;
import pro.shushi.pamirs.framework.connectors.data.sql.AbstractWrapper;
import pro.shushi.pamirs.framework.connectors.data.sql.query.QueryWrapper;
import pro.shushi.pamirs.meta.annotation.Hook;
import pro.shushi.pamirs.meta.api.Models;
import pro.shushi.pamirs.meta.api.core.faas.HookBefore;
import pro.shushi.pamirs.meta.api.core.orm.convert.ClientDataConverter;
import pro.shushi.pamirs.meta.api.core.orm.template.context.ModelComputeContext;
import pro.shushi.pamirs.meta.api.dto.config.ModelConfig;
import pro.shushi.pamirs.meta.api.dto.config.ModelFieldConfig;
import pro.shushi.pamirs.meta.api.dto.fun.Function;
import pro.shushi.pamirs.meta.api.session.PamirsSession;
import pro.shushi.pamirs.meta.base.D;
import pro.shushi.pamirs.meta.common.spi.Spider;
import pro.shushi.pamirs.meta.domain.model.ModelField;
import pro.shushi.pamirs.meta.enmu.TtypeEnum;
import pro.shushi.pamirs.resource.api.constants.FieldConstants;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 通用 queryData处理。
*/
@Slf4j
@Component
public class QueryDataHook implements HookBefore {
@Override
@Hook(priority = 30)
public Object run(Function function, Object... args) {
getValueByType(args);
return function;
}
private void getValueByType(Object... args) {
if (ArrayUtils.isEmpty(args)) {
return;
}
for (int index = 0; index < args.length && null != args[index]; ++index) {
if (args[index] instanceof AbstractWrapper) {
AbstractWrapper<?, ?, ?> wrapper = (AbstractWrapper<?, ?, ?>) args[index];
Map<String, Object> queryData = wrapper.getQueryData();
if (null == queryData) {
continue;
}
//有非存储字段
ModelConfig modelConfig = PamirsSession.getContext().getModelConfig(wrapper.getModel());
List<ModelFieldConfig> modelFieldConfigs = modelConfig.getModelFieldConfigList();
Map<String, ModelField> modelFieldMap = new HashMap<>();
for (ModelFieldConfig modelFieldConfig : modelFieldConfigs) {
modelFieldMap.put(modelFieldConfig.getField(), modelFieldConfig.getModelField());
}
for (Map.Entry<String, Object> entry : queryData.entrySet()) {
String key = entry.getKey();
ModelField field = modelFieldMap.get(key);
if (field != null && TtypeEnum.isRelatedType(field.getTtype().value())) {
//非存储字段是related字段
List<String> relateds = field.getRelated();
if (relateds != null && relateds.size() == 2) {
ModelField reletedField = modelFieldMap.get(relateds.get(0));
if (reletedField != null && TtypeEnum.isRelationType(reletedField.getTtype())) {
//是关系字段
String reletedModelQueryField = relateds.get(1);
String referenceModel = reletedField.getReferences();
ModelFieldConfig relatedFieldCfg = PamirsSession.getContext().getModelField(referenceModel, reletedModelQueryField);
Map<String, Object> relationMap = new HashMap<>();
Object value = entry.getValue();
relationMap.put(relatedFieldCfg.getField(), value);
relationMap.put(FieldConstants._dFieldName, referenceModel);
Object relationObj = Spider.getDefaultExtension(ClientDataConverter.class).in(new ModelComputeContext(), referenceModel, relationMap);
if (relationObj instanceof D) {
relationMap = ((D) relationObj).get_d();
} else {
relationMap = (Map<String, Object>) relationObj;
}
String column = relatedFieldCfg.getColumn();
QueryWrapper<D> wrapper1 = new QueryWrapper<D>();
wrapper1.from(referenceModel);
wrapper1.eq(column, relationMap.get(relatedFieldCfg.getField()));
List<D> values = Models.data().queryListByWrapper(wrapper1);
List<String> referenceFields = reletedField.getReferenceFields();
StringBuilder rsqlBuilder = new StringBuilder(wrapper.getRsql());
for (String refField : referenceFields) {
List<Object> list = new ArrayList<>();
for (D d : values) {
Object v = d.get_d().get(refField);
if (null != v) {
list.add(v);
}
}
if (CollectionUtils.isNotEmpty(list)) {
if (CollectionUtils.size(list) > 10000) {
log.warn("查询数量过多,请自定义查询逻辑,例如使用联表");
}
String vv = list.stream().map(String::valueOf).collect(Collectors.joining(","));
rsqlBuilder.append(" and ")
.append(reletedField.getRelationFields().get(0)).append(RSQLOperators.IN.getSymbol()).append("(").append(vv).append(")")
;
} else {
rsqlBuilder.append(" and (1!=1)");
}
}
wrapper.setRsql(rsqlBuilder.toString());
}
}
}
}
break;
}
}
}
}
Oinone社区 作者:yakir原创文章,如若转载,请注明出处:https://doc.oinone.top/backend/20267.html
访问Oinone官网:https://www.oinone.top获取数式Oinone低代码应用平台体验