查询时自定义排序字段和排序规则

指定字段排序

平台默认排序字段,参考IdModel,按创建时间和ID倒序(ordering = "createDate DESC, id DESC")

方法1:模型指定排序

模型定义增加排序字段。@Model.Advanced(ordering = "xxxxx DESC, yyyy DESC")

@Model.model(PetShop.MODEL_MODEL)
@Model(displayName = "宠物店铺",summary="宠物店铺",labelFields ={"shopName"})
@Model.Code(sequence = "DATE_ORDERLY_SEQ",prefix = "P",size=6,step=1,initial = 10000,format = "yyyyMMdd")
@Model.Advanced(ordering = "createDate DESC")
public class PetShop extends AbstractDemoIdModel {
       public static final String MODEL_MODEL="demo.PetShop";
       // …………
}

方法2:Page查询中可以自定排序规则

  • API参考 pro.shushi.pamirs.meta.api.dto.condition.Pagination#orderBy
    public <G, R> Pagination<T> orderBy(SortDirectionEnum direction, Getter<G, R> getter) {
     if (null == getSort()) {
         setSort(new Sort());
     }
     getSort().addOrder(direction, getter);
     return this;
    }
  • 具体示例
    @Function.Advanced(type= FunctionTypeEnum.QUERY)
    @Function.fun(FunctionConstants.queryPage)
    @Function(openLevel = {FunctionOpenEnum.API})
    public Pagination<PetShop> queryPage(Pagination<PetShop> page, IWrapper<PetShop> queryWrapper){
     page.orderBy(SortDirectionEnum.DESC, PetShop::getCreateDate);
     page = new PetShop().queryPage(page, queryWrapper);
     return page;
    }

方法3:查询的wapper中指定

  • API参考:pro.shushi.pamirs.framework.connectors.data.sql.AbstractWrapper#orderBy
    @Override
    public Children orderBy(boolean condition, boolean isAsc, R... columns) {
    if (ArrayUtils.isEmpty(columns)) {
        return typedThis;
    }
    SqlKeyword mode = isAsc ? ASC : DESC;
    for (R column : columns) {
        doIt(condition, ORDER_BY, columnToString(column), mode);
    }
    return typedThis;
    }

具体示例

public List<PetShop> queryList(String name) {
    List<PetShop> petShops = Models.origin().queryListByWrapper(
            Pops.<PetShop>lambdaQuery().from(PetShop.MODEL_MODEL)
                    .orderBy(true, true, PetShop::getCreateDate)
                   .orderBy(true, true, PetShop::getId)
                    .like(PetShop::getShopName, name));
    return petShops;
}

设置查询不排序

方法1:关闭平台默认排序字段,设置模型的ordering,改成:ordering = "1=1"

模型定义增加排序字段。@Model.Advanced(ordering = "1=1")

@Model.model(PetShop.MODEL_MODEL)
@Model(displayName = "宠物店铺",summary="宠物店铺",labelFields ={"shopName"})
@Model.Code(sequence = "DATE_ORDERLY_SEQ",prefix = "P",size=6,step=1,initial = 10000,format = "yyyyMMdd")
@Model.Advanced(ordering = "1=1")
public class PetShop extends AbstractDemoIdModel {
       public static final String MODEL_MODEL="demo.PetShop";
       // …………
}

在ORDER BY 1=1中,1=1是一个条件表达式,它总是会返回true(或者在某些数据库中是1),因为1等于1。因此,这个条件实际上没有改变排序的结果,结果仍然会按照默认的顺序进行排序。这种写法通常用于一些动态生成SQL语句的场景中,可以在不知道具体列名的情况下按照顺序进行排序。

所以,ORDER BY 1=1实际上等效于没有使用ORDER BY子句,或者说是按照默认顺序进行排序。

方法2:查询是设置Sortable属性

// 示例1:
LambdaQueryWrapper<PetShop> query = Pops.<PetShop>lambdaQuery();
query.from(PetShop.MODEL_MODEL);
query.setSortable(Boolean.FALSE);
query.orderBy(true, true, PetShop::getId);
List<PetShop> petShops2 = new PetShop().queryList(query);
System.out.printf(petShops2.size() + "");

// 示例2:
List<PetShop> petShops3 = new PetShop().queryList(
        Pops.<PetShop>lambdaQuery().from(PetShop.MODEL_MODEL).setSortable(Boolean.FALSE));
System.out.printf(petShops3.size() + "");

// 示例3:
IWrapper<PetShop> wrapper = Pops.<PetShop>lambdaQuery()
        .from(PetShop.MODEL_MODEL).setBatchSize(-1).setSortable(Boolean.FALSE);
List<PetShop> petShops4 = new PetShop().queryList(wrapper);
System.out.printf(petShops4.size() + "");

// 示例4:
QueryWrapper<PetShop> wrapper2 = new QueryWrapper<PetShop>().from(PetShop.MODEL_MODEL).setSortable(Boolean.FALSE);
List<PetShop> petShops5 = new PetShop().queryList(wrapper2);
System.out.printf(petShops5.size() + "");

Oinone社区 作者:望闲原创文章,如若转载,请注明出处:https://doc.oinone.top/backend/11449.html

访问Oinone官网:https://www.oinone.top获取数式Oinone低代码应用平台体验

(0)
望闲的头像望闲数式管理员
上一篇 2024年5月25日 pm4:47
下一篇 2024年5月25日 pm5:59

相关推荐

  • 代码示例:快速找到示例代码

    1、图表设计器 数据可视化能加载到的接口,方法上需要加 category = FunctionCategoryEnum.QUERY_PAGE @Model.model(ExpensesIncome.MODEL_MODEL) @Component @Slf4j public class ExpensesIncomeAction { @Function.Advanced(type = FunctionTypeEnum.QUERY,category = FunctionCategoryEnum.QUERY_PAGE) @Function.fun(FunctionConstants.queryPage) @Function(openLevel = {FunctionOpenEnum.API}) public Pagination<ExpensesIncome> queryPage(Pagination<ExpensesIncome> page, IWrapper<ExpensesIncome> queryWrapper) { page = new ExpensesIncome().queryPage(page, queryWrapper); if (page!=null && CollectionUtils.isNotEmpty(page.getContent())) { page.getContent().forEach(a->{ if (a.getBudgetInCome()!=null && a.getBudgetInCome().compareTo(new BigDecimal("0.0"))!=0) { if (a.getRetailAmount()!=null) { a.setInComeRate(a.getRetailAmount().divide(a.getBudgetInCome(),2)); } } }); } return page; } } 2、事务支持 1)对于单个系统(InJvm)/模型内部采用强事务的方式。比如:在库存转移时,库存日志和库存数量的变化在一个事务中,保证两个表的数据同时成功或者失败。2)强事务管理采用编码式,Oinone事务管理兼容Spring的事务管理方式;有注解的方式和代码块的方式。a) 使用注解的方式: @Override @Transactional public void awardOut(AwardBookOutEmpRecordDetail detail) { List<OutEmpRecordSubjectDetail> subjectDetails = detail.getSubjectDetails(); …… } 重要说明基于注解的事务,Bean和加注解的方法必须能被Spring切面到。 b) 使用编码方式: //组装数据/获取数据/校验 Tx.build(new TxConfig()).executeWithoutResult(status -> { // 1、保存部门数据 deliDepartmentService.createOrUpdateBatch(departments); //2、如果父进行了下级关联设置,处理下级关联设置的逻辑 for (DeliDepartment department : departments) { doDepartSubLink(department); } }); ………… 3)对于分布式事务采用最终数据一致性,借助【可靠消息】或者【Job】的方式来实现。 3、平台工具类使用 3.1 FetchUtil pro.shushi.pamirs.core.common.FetchUtil,重点关注 # 根据Id查询列表 pro.shushi.pamirs.core.common.FetchUtil#fetchMapByIds # 根据Id查询,返回Map pro.shushi.pamirs.core.common.FetchUtil#fetchListByIds # 根据Codes查询列表 pro.shushi.pamirs.core.common.FetchUtil#fetchMapByCodes # 根据Code查询,返回Map pro.shushi.pamirs.core.common.FetchUtil#fetchListByCodes # 根据Entity查询 pro.shushi.pamirs.core.common.FetchUtil#fetchOne 其他更多方法参考这个类的源代码 3.2 ListUtils pro.shushi.pamirs.meta.common.util.ListUtils # 把输入的List,按给定的长度进行分组 pro.shushi.pamirs.meta.common.util.ListUtils#fixedGrouping # 从给定的List中返回特定字段的数组,忽略Null并去重 pro.shushi.pamirs.meta.common.util.ListUtils#transform 4、枚举获取 根据枚举的name获取valueInteger value = ArchivesConfigTypeEnum.getValueByName(ArchivesConfigTypeEnum.class,“status1”);根据枚举的name获取枚举项ArchivesConfigTypeEnum typeEnum = TtypeEnum.getEnum(ArchivesConfigTypeEnum.class, “status1”); 5、Map类型的数据怎么定义,即ttype 为map的字段写法 @Field(displayName = "上下文", store = NullableBoolEnum.TRUE, serialize = JSON) @Field.Advanced(columnDefinition = "TEXT") private Map<String, Object> context; 6、后端获取前端请求中的variables PamirsRequestVariables requestVariables = PamirsSession.getRequestVariables(); 7、为什么有时候调用服务走远程了 1、假设: A模型(modelA)所在的模块(ModuleA) B模型(modelB)所在的模块(ModuleB) 部署方式决定调用方式: 1)部署方式1: ModuleA 和 ModuleB 部署在一个jvm中,此时: modelA的服务/页面去调用 modelB,因为部署在一起,直接走inJvm 2、部署方式2: ModuleA 和 ModuleB 部署在不同的jvm中; modelA的服务/页面去调用 modelB,则会走远程(RPC);此时需要: a)ModuleB 需要开启dubbo服务,且ModuleA 和 ModuleB注册中心相同…

    2024年2月20日
    1.3K00
  • Oinone请求路由源码分析

    通过源码分析,从页面发起请求,如果通过graphQL传输到具体action的链路,并且在这之间做了哪些隐式处理分析源码版本5.1.x 请求流程大致如下: 拦截所有指定的请求 组装成graphQL请求信息 调用graphQL执行 通过hook拦截先执行 RsqlDecodeHook:rsql解密 UserHook: 获取用户信息, 通过cookies获取用户ID,再查表获取用户信息,放到本地Local线程里 RoleHook: 角色Hook FunctionPermissionHook: 函数权限Hook ,跳过权限拦截的实现放在这一层,对应的配置 pamirs: auth: fun-filter: – namespace: user.PamirsUserTransient fun: login #登录 – namespace: top.PetShop fun: action DataPermissionHook: 数据权限hook PlaceHolderHook:占位符转化替换hook RsqlParseHook: 解释Rsql hook SingletonModelUpdateHookBefore 执行post具体内容 通过hook拦截后执行 QueryPageHook4TreeAfter: 树形Parent查询优化 FieldPermissionHook: 字段权限Hook UserQueryPageHookAfter UserQueryOneHookAfter 封装执行结果信息返回 时序图 核心源码解析 拦截所有指定的请求 /pamirs/模块名RequestController @RequestMapping( value = "/pamirs/{moduleName:^[a-zA-Z][a-zA-Z0-9_]+[a-zA-Z0-9]$}", method = RequestMethod.POST ) public String pamirsPost(@PathVariable("moduleName") String moduleName, @RequestBody PamirsClientRequestParam gql, HttpServletRequest request, HttpServletResponse response) { } DefaultRequestExecutor 构建graph请求信息,并调用graph请求 () -> execute(GraphQL::execute, param), param private <T> T execute(BiFunction<GraphQL, ExecutionInput, T> executor, PamirsRequestParam param) { // 获取GraphQL请求信息,包含grapsh schema GraphQL graphQL = buildGraphQL(param); … ExecutionInput executionInput = ExecutionInput.newExecutionInput() .query(param.getQuery()) .variables(param.getVariables().getVariables()) .dataLoaderRegistry(Spider.getDefaultExtension(DataLoaderRegistryApi.class).dataLoader()) .build(); … // 调用 GraphQL的方法execute 执行 T result = executor.apply(graphQL, executionInput); … return result; } QueryAndMutationBinder 绑定graphQL读取写入操作 public static DataFetcher<?> dataFetcher(Function function, ModelConfig modelConfig) { if (isAsync()) { if (FunctionTypeEnum.QUERY.in(function.getType())) { return AsyncDataFetcher.async(dataFetchingEnvironment -> dataFetcherAction(function, modelConfig, dataFetchingEnvironment), ExecutorServiceApi.getExecutorService()); } else { return dataFetchingEnvironment -> dataFetcherAction(function, modelConfig, dataFetchingEnvironment); } } else { return dataFetchingEnvironment -> dataFetcherAction(function, modelConfig, dataFetchingEnvironment); } } private static Object dataFetcherAction(Function function, ModelConfig modelConfig, DataFetchingEnvironment environment) { try { SessionExtendUtils.tagMainRequest(); // 使用共享的请求和响应对象 return Spider.getDefaultExtension(ActionBinderApi.class) .action(modelConfig,…

    2024年8月21日
    5.6K02
  • 复杂Excel模版定义

    模版示例: Demo Excel样例 代码示例: @Model.model(TestApply.MODEL_MODEL) @Model(displayName = "测试申请") public class TestApply extends IdModel { public static final String MODEL_MODEL = "top.TestApply"; @Field.String @Field(displayName = "发件人") private String addresser; @Field.String @Field(displayName = "委托单位") private String entrustedUnit; @Field.String @Field(displayName = "付款单位") private String payer; @Field.String @Field(displayName = "付款单位地址") private String paymentUnitAdd; } 模版: package pro.shushi.pamirs.top.core.temp; import org.springframework.stereotype.Component; import pro.shushi.pamirs.file.api.builder.SheetDefinitionBuilder; import pro.shushi.pamirs.file.api.builder.WorkbookDefinitionBuilder; import pro.shushi.pamirs.file.api.enmu.ExcelAnalysisTypeEnum; import pro.shushi.pamirs.file.api.enmu.ExcelDirectionEnum; import pro.shushi.pamirs.file.api.enmu.ExcelHorizontalAlignmentEnum; import pro.shushi.pamirs.file.api.model.ExcelWorkbookDefinition; import pro.shushi.pamirs.file.api.util.ExcelHelper; import pro.shushi.pamirs.file.api.util.ExcelTemplateInit; import pro.shushi.pamirs.top.api.model.TestApply; import java.util.Collections; import java.util.List; @Component public class DemoTemplate implements ExcelTemplateInit { public static final String TEMPLATE_NAME = "DemoTemplate"; @Override public List<ExcelWorkbookDefinition> generator() { WorkbookDefinitionBuilder builder = WorkbookDefinitionBuilder.newInstance(TestApply.MODEL_MODEL, TEMPLATE_NAME) .setDisplayName("测试Demo"); DemoTemplate.createSheet(builder); return Collections.singletonList(builder.build()); } private static void createSheet(WorkbookDefinitionBuilder builder) { SheetDefinitionBuilder sheetBuilder = builder.createSheet().setName("测试Demo"); buildBasicInfo(sheetBuilder); } private static void buildBasicInfo(SheetDefinitionBuilder builder) { //A1:D8:表示表头占的单元格数,范围必须大于实际表头行 BlockDefinitionBuilder mergeRange = builder.createBlock(TestApply.MODEL_MODEL, ExcelAnalysisTypeEnum.FIXED_HEADER, ExcelDirectionEnum.HORIZONTAL, "A1:D8") //预设行 .setPresetNumber(10) //合并哪几个单元格 .createMergeRange("A1:D1") .createMergeRange("A2:D2") .createMergeRange("A3:D3") .createMergeRange("A4:A6") .createMergeRange("B4:B6") .createMergeRange("C4:C6") .createMergeRange("D4:D5"); //createHeader创建行,createCell创建单元格,setField指定解析字段,setIsConfig指定为true标记该行是需要解析的值 mergeRange.createHeader().setStyleBuilder(ExcelHelper.createDefaultStyle()).setIsConfig(Boolean.TRUE) .createCell().setField("addresser").setStyleBuilder(ExcelHelper.createDefaultStyle().setWidth(6000)).and() .createCell().setField("entrustedUnit").and() .createCell().setField("payer").and() .createCell().setField("paymentUnitAdd").and() .and() .createHeader().setStyleBuilder(ExcelHelper.createDefaultStyle(typeface -> typeface.setBold(Boolean.TRUE)).setHorizontalAlignment(ExcelHorizontalAlignmentEnum.CENTER)) .createCell().setValue("Demo").and() .createCell().and() .createCell().and() .createCell().and() .and() //由于该行合并为一个单元格,所以其他可以不设置value .createHeader().setStyleBuilder(ExcelHelper.createDefaultStyle(typeface -> typeface.setBold(Boolean.TRUE)).setHorizontalAlignment(ExcelHorizontalAlignmentEnum.CENTER)) .createCell().setValue("生效金额").and() .createCell().and() .createCell().and() .createCell().and() .and() .createHeader().setStyleBuilder(ExcelHelper.createDefaultStyle(typeface -> typeface.setBold(Boolean.TRUE)).setHorizontalAlignment(ExcelHorizontalAlignmentEnum.RIGHT)) .createCell().setValue("金额单位:元").and() .createCell().and() .createCell().and() .createCell().and() .and() //easyExcel解析不了空行,所以这里写上值。由于上面使用createMergeRange把单元格合并了,并且D列有分割,这里填上每个单元格的值,把合并的单元格填为一样的。 .createHeader().setStyleBuilder(ExcelHelper.createDefaultStyle(typeface -> typeface.setBold(Boolean.TRUE)).setHorizontalAlignment(ExcelHorizontalAlignmentEnum.CENTER)) .createCell().setValue("发件人").and() .createCell().setValue("委托单位").and()…

    2024年11月18日
    2.1K00
  • 如何在代码中使用自增ID和获取序列

    在使用继承IDModel或CodeModel时,id和code是系统默认自动生成, 默认值规则:ID–>分布式ID; CODE–>根据定义的SequenceConfig规则自动生成。 在特定情况下需要落库前先生成ID或者Code,这些场景下可参照如下代码示例 一、使用自增ID 单个字段设置方式 // 主键字段,可以使用mysql的自增能力 @Field.Integer @Field.PrimaryKey(keyGenerator = KeyGeneratorEnum.AUTO_INCREMENT) @Field.Advanced(batchStrategy = FieldStrategyEnum.NEVER) @Field(displayName = "id", summary = "Id字段,⾃增") private Long id; @Field.Integer @Field(displayName = "自增版本") @Field.Sequence(sequence = "SEQ", initial = 1) private Long version; 全局设置方式 该方式会作用到每一个存储模型的id字段,在application.yml配置文件中修改id的生成规则,查找配置项关键字key-generator,默认为DISTRIBUTION(分布式id),可修改为 AUTO_INCREMENT(自增id) 二、手动方式获取序列 获取方式示例1 /** * 在特定场景下需要手动生成Id或者code时,可参照这个示例 */ public void manualSetIdCode(){ DemoItem demoItem = new DemoItem(); //手动生成ID和code Object idObj = Spider.getDefaultExtension(IdGenerator.class).generate(PamirsTableInfo.fetchKeyGenerator(DemoItem.MODEL_MODEL)); demoItem.setId(TypeUtils.createLong(idObj)); Object codeObj = CommonApiFactory.getSequenceGenerator().generate("SEQ",DemoItem.MODEL_MODEL); String code = TypeUtils.stringValueOf(codeObj); demoItem.setCode(code); //…… } 获取方式示例2 1、在系统启动的时候初始化SequenceConfig package pro.shushi.pamirs.demo.core.init; import org.springframework.stereotype.Component; import pro.shushi.pamirs.boot.common.api.command.AppLifecycleCommand; import pro.shushi.pamirs.boot.common.extend.MetaDataEditor; import pro.shushi.pamirs.core.common.InitializationUtil; import pro.shushi.pamirs.demo.api.DemoModule; import pro.shushi.pamirs.demo.core.constant.SeqConstants; import pro.shushi.pamirs.meta.annotation.fun.extern.Slf4j; import pro.shushi.pamirs.meta.api.dto.meta.Meta; import pro.shushi.pamirs.meta.enmu.SequenceEnum; import java.util.Map; /** * DemoMetadataEditor */ @Slf4j @Component public class DemoMetadataEditor implements MetaDataEditor { @Override public void edit(AppLifecycleCommand command, Map<String, Meta> metaMap) { InitializationUtil util = InitializationUtil.get(metaMap, DemoModule.MODULE_MODULE, DemoModule.MODULE_NAME); if (util == null) { log.error("获取初始化序列失败"); return; } bizSequence(util); } private void bizSequence(InitializationUtil util) { util.createSequenceConfig("申请单编码生成", SeqConstants.NABEL_SAMPLE_APPLY_SEQ, SequenceEnum.ORDERLY_SEQ, 8) .setStep(1) .setInitial(80000000L) .setIsRandomStep(false); util.createSequenceConfig("订单编码生成", SeqConstants.NABEL_SAMPLE_ORDER_SEQ_YP, SequenceEnum.ORDERLY_SEQ, 8) .setPrefix("YP") .setStep(1) .setInitial(80000000L) .setIsRandomStep(false); } } 2、在代码中使用序列 public static String getSaleOrderCode() { Object sequence = CommonApiFactory.getSequenceGenerator().generate(SequenceEnum.ORDERLY_SEQ.value(), SeqConstants.NABEL_SAMPLE_STRUCTURE_SEQ); return TypeUtils.stringValueOf(sequence); } public static String getApplyOrderCode(String prefix) { Object sequence = CommonApiFactory.getSequenceGenerator().generate(SequenceEnum.ORDERLY_SEQ.value(), SeqConstants.NABEL_SAMPLE_APPLY_SEQ); return…

    2024年5月25日
    1.8K00
  • EIP开放接口使用MD5验签发起请求(v5.x)

    验签工具类 PS:该验签方法仅在pamirs-core的5.0.16版本以上可正常使用 public class EipSignUtils { public static final String SIGN_METHOD_MD5 = "md5"; private static final String SIGN_METHOD_HMAC = "hmac"; private static final String SECRET_KEY_ALGORITHM = "HmacMD5"; private static final String MESSAGE_DIGEST_MD5 = "MD5"; public static String signTopRequest(Map<String, String> params, String secret, String signMethod) throws IOException { // 第一步:检查参数是否已经排序 String[] keys = params.keySet().toArray(new String[0]); Arrays.sort(keys); // 第二步:把所有参数名和参数值串在一起 StringBuilder query = new StringBuilder(); if (SIGN_METHOD_MD5.equals(signMethod)) { query.append(secret); } for (String key : keys) { String value = params.get(key); if (StringUtils.isNoneBlank(key, value)) { query.append(key).append(value); } } // 第三步:使用MD5/HMAC加密 byte[] bytes; if (SIGN_METHOD_HMAC.equals(signMethod)) { bytes = encryptHMAC(query.toString(), secret); } else { query.append(secret); bytes = encryptMD5(query.toString()); } // 第四步:把二进制转化为大写的十六进制(正确签名应该为32大写字符串,此方法需要时使用) return byte2hex(bytes); } private static byte[] encryptHMAC(String data, String secret) throws IOException { byte[] bytes; try { SecretKey secretKey = new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), SECRET_KEY_ALGORITHM); Mac mac = Mac.getInstance(secretKey.getAlgorithm()); mac.init(secretKey); bytes = mac.doFinal(data.getBytes(StandardCharsets.UTF_8)); } catch (GeneralSecurityException e) { throw new IOException(e.toString(), e); } return bytes; } private static byte[] encryptMD5(String data) throws IOException { return encryptMD5(data.getBytes(StandardCharsets.UTF_8)); } private static byte[] encryptMD5(byte[] data) throws IOException { try { MessageDigest md = MessageDigest.getInstance(MESSAGE_DIGEST_MD5); return md.digest(data); } catch (NoSuchAlgorithmException e)…

    2024年6月29日
    1.4K00

Leave a Reply

登录后才能评论