如何自定义SQL(Mapper)语句

场景描述

在实际业务场景中,存在复杂SQL的情况,具体表现为:

  • 单表单SQL满足不了的情况下
  • 有复杂的Join关系或者子查询
  • 复杂SQL的逻辑通过程序逻辑难以实现或实现代价较大

在此情况下,通过原生的mybatis/mybatis-plus, 自定义Mapper的方式实现业务功能

1、编写所需的Mapper

SQL Mapper写法无限制,与使用原生的mybaits/mybaits-plus用法一样; Mapper(DAO)和SQL可以写在一个文件中,也分开写在两个文件中。

package pro.shushi.pamirs.demo.core.map;

import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;

import java.util.List;
import java.util.Map;

@Mapper
public interface DemoItemMapper {
    @Select("<script>select sum(item_price) as itemPrice,sum(inventory_quantity) as inventoryQuantity,categoryId from ${demoItemTable}  as core_demo_item ${where}  group by category_id</script>")
    List<Map<String, Object>> groupByCategoryId(@Param("demoItemTable") String pamirsUserTable, @Param("where") String where);
}

2.调用mapper

调用Mapper代码示例

package pro.shushi.pamirs.demo.core.map;

import com.google.api.client.util.Lists;
import org.springframework.stereotype.Component;
import pro.shushi.pamirs.demo.api.model.DemoItem;
import pro.shushi.pamirs.framework.connectors.data.api.datasource.DsHintApi;
import pro.shushi.pamirs.meta.api.core.orm.convert.DataConverter;
import pro.shushi.pamirs.meta.api.session.PamirsSession;
import pro.shushi.pamirs.meta.common.spring.BeanDefinitionUtils;

import java.util.List;
import java.util.Map;

@Component
public class DemoItemDAO {
    public List<DemoItem> customSqlDemoItem(){
        try (DsHintApi dsHint = DsHintApi.model(DemoItem.MODEL_MODEL)) {
            String demoItemTable = PamirsSession.getContext().getModelCache().get(DemoItem.MODEL_MODEL).getTable();

            DemoItemMapper demoItemMapper = BeanDefinitionUtils.getBean(DemoItemMapper.class);
            String where = " where status = 'ACTIVE'";
            List<Map<String, Object>> dataList = demoItemMapper.groupByCategoryId(demoItemTable,where);
            DataConverter persistenceDataConverter = BeanDefinitionUtils.getBean(DataConverter.class);
            return persistenceDataConverter.out(DemoItem.MODEL_MODEL, dataList);
        }
        return Lists.newArrayList();
    }
}

调用Mapper一些说明

  • 启动类需要配置扫描包MapperScan
    @MapperScan(value = "pro.shushi", annotationClass = Mapper.class)
    @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, FreeMarkerAutoConfiguration.class})
    public class DemoApplication {
  • 调用Mapper接口的时候,需要指定数据源;即上述示例代码中的 DsHintApi dsHint = DsHintApi.model(DemoItem.MODEL_MODEL), 实际代码中使用 try-with-resources语法。
  • 从Mapper返回的结果中获取数据
    • 如果SQL Mapper中已定义了resultMap,调用Mapper(DAO)返回的就是Java对象
    • 如果Mapper返回的是Map<String, Object>,则通过 DataConverter.out进行转化,参考上面的示例

其他参考:Oinone连接外部数据源方案:https://doc.oinone.top/backend/4562.html

Oinone社区 作者:数式-海波原创文章,如若转载,请注明出处:https://doc.oinone.top/backend/4759.html

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

(0)
数式-海波的头像数式-海波数式管理员
上一篇 2023年11月24日 pm4:51
下一篇 2023年11月27日 pm4:30

相关推荐

  • docker status exited(255)

    虚拟机异常退出再启动后,docker run 出现错误: 查看所有容器发现确实存在一个容器,status是 exited(255) docker container ls -all 删除这个容器,命令 docker run 容器id docker rm 56e0  

    2024年11月23日
    72000
  • OSS(CDN)配置和文件系统的一些操作

    目前Oinone支持的OSS类型 类型 服务 OSS 阿里云OSS UPYUN 又拍云 MINIO MinIO HUAWEI_OBS 华为云OBS LOCAL 本地NGINX文件存储 TENCENT_COS 腾讯云COS OSS通用yaml配置 cdn: oss: name: # 名称 type: # 类型 bucket: uploadUrl: # 上传URL downloadUrl: # 下载URL accessKeyId: accessKeySecret: mainDir: # 主目录 validTime: 3600000 timeout: 600000 active: true referer: localFolderUrl: others: [key]: name: # 名称 type: # 类型 bucket: uploadUrl: # 上传URL downloadUrl: # 下载URL accessKeyId: accessKeySecret: mainDir: # 主目录 validTime: 3600000 timeout: 600000 active: true referer: localFolderUrl: PS:others中使用自定义key来指定OSS服务进行文件上传/下载功能。上传/下载必须匹配,否则无法正常使用。 OSS配置示例 阿里云OSS cdn: oss: name: 阿里云 type: OSS bucket: pamirs(根据实际情况修改) uploadUrl: oss-cn-hangzhou.aliyuncs.com downloadUrl: oss-cn-hangzhou.aliyuncs.com accessKeyId: 你的accessKeyId accessKeySecret: 你的accessKeySecret # 根据实际情况修改 mainDir: upload/ validTime: 3600000 timeout: 600000 active: true imageResizeParameter: referer: 华为云OBS cdn: oss: name: 华为云 type: HUAWEI_OBS bucket: pamirs(根据实际情况修改) uploadUrl: obs.cn-east-2.myhuaweicloud.com downloadUrl: obs.cn-east-2.myhuaweicloud.com accessKeyId: 你的accessKeyId accessKeySecret: 你的accessKeySecret # 根据实际情况修改 mainDir: upload/ validTime: 3600000 timeout: 600000 active: true allowedOrigin: http://192.168.95.31:8888,https://xxxx.xxxxx.com referer: 华为云OBS需要在启动工程增加以下依赖 <okhttp3.version>4.9.3</okhttp3.version> <dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>okhttp</artifactId> <version>${okhttp3.version}</version> </dependency> 注意事项华为云OBS的防盗链配置,仅允许携带特定referer的才可以,而excel导入后端处理的逻辑匿名读的时候是不带referer的,所以会被拒绝 MINIO 文件系统,mino的配置: cdn: oss: name: minio type: MINIO bucket: pamirs(根据实际情况修改) uploadUrl: http://192.168.243.6:32190(根据实际情况修改) downloadUrl: http://192.168.243.6:9000(根据实际情况修改) accessKeyId: 你的accessKeyId accessKeySecret: 你的accessKeySecret # 根据实际情况修改 mainDir: upload/ validTime: 3600000 timeout: 600000 active: true referer: localFolderUrl: MINIO无公网访问地址下OSS的配置方式: https://doc.oinone.top/yun-wei-shi-jian/7112.html 又拍云 cdn: oss: name: 又拍云 type: UPYUN…

    后端 2023年11月1日
    1.5K00
  • 工作流用户待办过滤站内信

    工作流用户待办过滤站内信 全局过滤 启动工程application.yml中配置: pamirs: workflow: notify: false 个性化过滤 实现pro.shushi.pamirs.workflow.app.api.service.WorkflowMailFilterApi接口 返回true表示需要发送站内信 返回false表示不需要发送站内信 示例: import org.apache.commons.lang3.StringUtils; import pro.shushi.pamirs.message.model.PamirsMessage; import pro.shushi.pamirs.meta.annotation.Fun; import pro.shushi.pamirs.meta.annotation.Function; import pro.shushi.pamirs.user.api.model.PamirsUser; import pro.shushi.pamirs.workflow.app.api.model.WorkflowUserTask; import pro.shushi.pamirs.workflow.app.api.service.WorkflowMailFilterApi; /** * MyWorkflowMailFilterImpl * * @author yakir on 2025/02/24 16:28. */ @Fun(WorkflowMailFilterApi.FUN_NAMESPACE) public class MyWorkflowMailFilterImpl implements WorkflowMailFilterApi { @Override @Function public Boolean filter(WorkflowUserTask workflowUserTask, PamirsUser user, PamirsMessage message) { // 按用户待办过滤 workflowUserTask if (10000L == workflowUserTask.getInitiatorUid()){ return true; } // 按用户过滤 user if (1000L == user.getId()){ return true; } // 按站内信消息过滤 message if (StringUtils.contains(message.getBody(), "你好")) { return true; } return false; } }

    2025年2月24日
    91300
  • 【Excel导入/导出】多Sheet导入导出示例(4.7.x及以上版本)

    代码示例 示例仅供参考 点击下载代码示例 业务场景 准备工作:两个模型,物料(Material)和物料类别(MaterialCategory)。目标:在一个Excel模板中同时导入和导出两个模型的数据。 Material模型 @Model.model(Material.MODEL_MODEL) @Model.Advanced(unique = {"code"}) @Model(displayName = "物料", labelFields = {"name"}) public class Material extends IdModel { private static final long serialVersionUID = -2594216864389636135L; public static final String MODEL_MODEL = "maas.Material"; @Field.String @Field(displayName = "物料编码", required = true) private String code; @Field.String @Field(displayName = "物料名称", required = true) private String name; } MaterialCategory模型 @Model.model(MaterialCategory.MODEL_MODEL) @Model.Advanced(unique = {"code"}) @Model(displayName = "物料类别", labelFields = {"name"}) public class MaterialCategory extends IdModel { private static final long serialVersionUID = 6300896634558908349L; public static final String MODEL_MODEL = "maas.MaterialCategory"; @Field.String @Field(displayName = "类别编码", required = true) private String code; @Field.String @Field(displayName = "类别名称", required = true) private String name; } 模板定义 MaterialTemplate @Component public class MaterialTemplate implements ExcelTemplateInit { public static final String TEMPLATE_NAME = "materialTemplate"; @Override public List<ExcelWorkbookDefinition> generator() { WorkbookDefinitionBuilder builder = WorkbookDefinitionBuilder.newInstance(Material.MODEL_MODEL, TEMPLATE_NAME) .setDisplayName("物料和物料类别") .setEachImport(Boolean.FALSE);//设置importData的入参为 (ExcelImportContext importContext, List<MaterialCategory> data),如入参是单个对象,请删除setEachImport(Boolean.FALSE) createMaterialSheet(builder); createMaterialCategorySheet(builder); return Collections.singletonList(builder.build()); } private static void createMaterialSheet(WorkbookDefinitionBuilder builder) { builder.createSheet().setName("物料") .createBlock(Material.MODEL_MODEL, ExcelAnalysisTypeEnum.FIXED_HEADER, ExcelDirectionEnum.HORIZONTAL, "A1:B2") .createHeader().setStyleBuilder(ExcelHelper.createDefaultStyle()).setIsConfig(Boolean.TRUE) .createCell().setField("code").setAutoSizeColumn(Boolean.TRUE).and() .createCell().setField("name").setAutoSizeColumn(Boolean.TRUE).and() .and() .createHeader().setStyleBuilder(ExcelHelper.createDefaultStyle(v -> v.setBold(Boolean.TRUE)).setHorizontalAlignment(ExcelHorizontalAlignmentEnum.CENTER)) .createCell().setValue("物料编码").and() .createCell().setValue("物料名称"); } private static void createMaterialCategorySheet(WorkbookDefinitionBuilder builder) { builder.createSheet().setName("物料类别") .createBlock(MaterialCategory.MODEL_MODEL, ExcelAnalysisTypeEnum.FIXED_HEADER, ExcelDirectionEnum.HORIZONTAL, "A1:B2") .createHeader().setStyleBuilder(ExcelHelper.createDefaultStyle()).setIsConfig(Boolean.TRUE) .createCell().setField("code").setAutoSizeColumn(Boolean.TRUE).and()…

    2024年4月23日
    1.0K00
  • Oinone协同开发使用手册

    概述 Oinone平台为开发人员提供了本地环境 – 测试环境之间的协同开发模式,可以使得开发人员在本地环境中设计的模型、函数等元数据实时被测试环境使用并设计。开发人员开发完成对应页面和功能后,可以部署至测试环境直接进行测试。 本篇文章将详细介绍协同开发模式在实际开发中的应用及相关内容。 名词解释 本地环境: 开发人员的本地启动环境 测试环境: 在测试服务器上部署的业务测试环境,业务工程服务和设计器服务共用中间件 业务工程服务:在测试服务器上部署的业务工程 设计器服务: 在测试服务器上部署的设计器镜像 一套环境:以测试环境为例,业务工程服务和设计器服务共同组成一套环境 生产环境: 在生产服务器上部署的业务生产环境 环境准备 部署了一个可用的设计器服务,并能正常访问。(需参照下文启动设计器环境内容进行相应修改) 准备一个用于开发的java工程。 准备一个用于部署测试环境的服务器。 协同参数介绍 用于测试环境的参数 -PmetaProtected=${value} 启用元数据保护,只有配置相同启动参数的服务才允许对元数据进行更新。通常该命令用于设计器服务和业务工程服务,并且两个环境需使用相同的元数据保护标记(value)进行启动。本地环境不使用该命令,以防止本地环境在协同开发时意外修改测试环境元数据,导致元数据混乱。 用法 java -jar boot.jar -PmetaProtected=pamirs 用于本地环境的配置 使用命令配置ownSign(推荐) java -jar boot.jar –pamirs.distribution.session.ownSign=demo 使用yaml配置ownSign pamirs: distribution: session: allMetaRefresh: false # 启用元数据全量刷新(备用配置,如遇元数据错误或混乱,启用该配置可进行恢复,使用一次后关闭即可) ownSign: demo # 协同开发元数据隔离标记,用于区分不同开发人员的本地环境,其他环境不允许使用 启动设计器环境 docker-run启动 -e PROGRAM_ARGS=-PmetaProtected=pamirs docker-compose启动 services: backend: container_name: designer-backend image: harbor.oinone.top/oinone/designer-backend-v5.0 restart: always environment: # 指定spring.profiles.active ARG_ENV: dev # 指定-Plifecycle ARG_LIFECYCLE: INSTALL # jvm参数 JVM_OPTIONS: "" # 程序参数 PROGRAM_ARGS: "-PmetaProtected=pamirs" PS: java [JVM_OPTIONS?] -jar boot.jar [PROGRAM_ARGS?] 开发流程示例图 具体使用步骤详见协同开发支持

    2024年7月24日
    1.7K00

Leave a Reply

登录后才能评论