脱离枯燥的CRUD,灵活使用Mybatis,根据mybatis动态的xml片段和接口规范动态生成代理类,轻松应付简单业务场景。

需求

需求是这样的,我们有一个数据服务平台的产品,用户先将数据源信息保存到平台上,一个数据源可以提供多个接口服务,而每个接口服务在数据库中存一个具有mybatis语法的sql片段。这样的话,对于一些简单的业务只需要编写好sql保存到数据库中然后提供一个接口文档就可以实现了。我们只需要对外提供一个http接口,http接口参数是接口服务ID和sql的参数。

保存在数据库中的xml片段大致如下:

select * from student as s left join score as sc on s.sno = sc.sno
<where><if sname != null and sname != ''>s.sname = #{sname}</if>
</where>

思路

从数据库中获取到xml文本片段后,如果手动去解析mybatis的各种标签和其中的OGNL表达式的话,无疑是一件很累人的事情。所以换种思路,既然功能是按照mybatis的规范来做的,那么mybatis有没有现成的API提供给我们使用呢?当然是有的,示例如下:

实现

  1. 先定义一套查询规范,也就是Mapper接口

    
    import java.util.List;
    import java.util.Map;/*** @author m*/
    public interface CommonMapper {/*** 查询列表** @param params* @return*/List<Map<String, Object>> selectList(Map<String, Object> params);/*** 查询单个** @param params* @return*/Map<String, Object> selectOne(Map<String, Object> params);
    }
    
  2. 再定义一套业务规范,也就是Service接口

    
    import java.util.List;
    import java.util.Map;/*** @author m*/
    public interface CommonService {/*** 查询列表** @param sql* @param params* @return*/List<Map<String, Object>> selectList(String sql, Map<String, Object> params);/*** 查询单个** @param params* @return*/Map<String, Object> selectOne(Map<String, Object> params);
    }
  3. 实现业务规范,在这里我们只实现查询列表的功能,其他的也就类似了。这里是没有实现数据源的切换和分页功能的,可以查询一下mybatis怎么切换数据源、PageHelper怎么去适配多数据源下的分页功能。当然也可以在评论区留言或者给我私信的。

    import com.demo.common.mapper.CommonMapper;
    import com.demo.common.service.CommonService;
    import org.apache.ibatis.builder.xml.XMLMapperBuilder;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.springframework.stereotype.Service;import javax.annotation.Resource;
    import java.io.ByteArrayInputStream;
    import java.io.InputStream;
    import java.nio.charset.StandardCharsets;
    import java.util.Collections;
    import java.util.List;
    import java.util.Map;@Service
    public class CommonServiceImpl implements CommonService {@Resourceprivate SqlSessionFactory sqlSessionFactory;/*** 查询列表** @param params* @return*/@Overridepublic List<Map<String, Object>> selectList(String sql, Map<String, Object> params) {String sqlXml = wrapSql2SelectListXml(sql);InputStream inputStream = new ByteArrayInputStream(sqlXml.getBytes(StandardCharsets.UTF_8));// 手动加载 XML 配置到 MyBatisXMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(inputStream, sqlSessionFactory.getConfiguration(), "dynamic-mapper", sqlSessionFactory.getConfiguration().getSqlFragments());xmlMapperBuilder.parse();// 获取 SqlSession 并执行查询try (SqlSession session = sqlSessionFactory.openSession()) {CommonMapper mapper = session.getMapper(CommonMapper.class);return mapper.selectList(params);} catch (Exception e) {e.printStackTrace();}return Collections.emptyList();}/*** 查询单个** @param params* @return*/@Overridepublic Map<String, Object> selectOne(Map<String, Object> params) {// TODO 待实现return Collections.emptyMap();}/*** 将sql封装为一个完整的xml,对应CommonMapper::selectList接口** @param sql* @return*/private String wrapSql2SelectListXml(String sql) {String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"+ "<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">"+ "<mapper namespace='com.demo.common.mapper.CommonMapper'>"+ "  <select id='selectList' resultType='java.util.Map'>"+ 		sql+ "  </select>"+ "</mapper>";return xml;}}
  4. 测试,经过测试是OK的。

    
    import com.demo.common.service.CommonService;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;
    import java.util.List;
    import java.util.Map;@RestController
    @RequestMapping("test")
    public class TestController {@Resourceprivate CommonService commonService;@RequestMapping("list")public Object test(@RequestParam Map<String, Object> params) {List<Map<String, Object>> maps = commonService.selectList("SELECT * FROM datagov.dg_alg WHERE alg_id = #{algId}", params);System.out.println(maps);return maps;}
    }

    在这里插入图片描述

总结

通过以上实现,不难发现,以上解决方案无非就是改变了Mybatis生成代理类的时机而已。在平常,Mybatis是通过扫描指定的xml目录和mapper接口,然后在容器启动时生成代理对象。而此时,我们是在方法执行的时候动态获取的xml并生成的动态的代理对象。两者使用起来是没有什么差别的。

当然以上只是平台一部分功能,像参数和结果集的提取,参数的校验,接口的鉴权、精细化控制、限流、负载均衡、熔断、幂等性,数据的分页处理、缓存等,在这里就不一一赘述了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/430202.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

电力施工作业安全行为检测图像数据集

电力施工作业安全行为检测图像数据集&#xff0c;图片总共 2300左右&#xff0c;标注为voc(xml)格式&#xff0c;包含高空抛物&#xff0c;未佩戴安全带&#xff0c;高处作业无人监护等。 电力施工作业安全行为检测图像数据集 数据集描述 这是一个专门用于电力施工作业安全行…

Drive.js 的一些 Api 使用记录

文章目录 2024 年 drive.js 的基础使用想在下一步的时候处理些逻辑呢&#xff1f;(同步)Element 的各种选择器 2024 年 drive.js 的基础使用 安装就跳过了 npm install driver.js &#xff0c;一行代码就可以搞定 官网的 Basic Usage 基础使用的截图如下&#xff1a; 想在下…

SLAM实操入门(八):使用Robosence-16转换数据格式,进行基于A-Loam的三维SLAM

文章目录 前言1 Robosence与Velodyne格式差异.2 格式转换2.1 rs_to_velodyne库2.2 目前支持&#xff1a; 3 拉取工程并编译2.1 安装robosence雷达驱动&#xff08;类似第六章&#xff09;&#xff1a;2.2 构建rs2vel工程&#xff1a; 3 运行robosence雷达&#xff0c;并转换格式…

2012年408考研真题-数据结构

8.【2012统考真题】求整数n(n≥0)的阶乘的算法如下&#xff0c;其时间复杂度是(&#xff09;。 int fact(int n){ if(n<1) return 1; return n*fact (n-1); } A. O(log2n) B. O(n) C. O(nlog2n) D. O(n^2) 解析&#xff1a; 观察代码&#xff0c;我们不…

Matlab Simulink 主时间步(major time step)、子时间步(minor time step)

高亮颜色说明&#xff1a;突出重点 个人觉得&#xff0c;&#xff1a;待核准个人观点是否有误 高亮颜色超链接 文章目录 对Simulink 时间步的理解Simulink 采样时间的类型Discrete Sample Times(离散采样时间)Controllable Sample Time(可控采样时间) Continuous Sample Times(…

在MAC中Ollama开放其他电脑访问

ollama安装完毕后默认只能在本地访问&#xff0c;之前我都是安装其他的软件之后可以结合开放其他端口访问&#xff0c;其实是可以新增或修改下电脑的系统配置&#xff0c;就可以打开端口允许除本机IP或localhost访问。 步骤如下&#xff1a; 1、查看端口&#xff08;默认是&…

Shelly实测天工的音乐创作功能,写了一首歌,来听听效果

​ 大家好&#xff0c;我是Shelly&#xff0c;一个专注于输出AI工具和科技前沿内容的AI应用教练&#xff0c;体验过300款以上的AI应用工具。关注科技及大模型领域对社会的影响10年。关注我一起驾驭AI工具&#xff0c;拥抱AI时代的到来。 在数字时代的洪流中&#xff0c;我始终…

杀软对抗 ---> Perfect Syscall??

好久没更了&#xff0c;今天想起来更新了&#x1f60b;&#x1f60b;&#x1f60b;&#x1f60b; 目录 1.AV && EDR 2.Perfect Syscall&#xff1f;&#xff1f; 3.Truly Perfect ??? 在开始之前先来展示一下这次的免杀效果 1.AV && EDR 360 天擎EDR …

Python模块和包:自定义模块和包③

文章目录 一、模块1.1 什么是模块1.2 创建模块1.3 导入模块1.4 模块的命名空间 二、包2.1 什么是包2.2 创建包2.3 导入包2.4 包的命名空间 三、综合详细例子3.1 项目结构3.2 模块代码student.pycourse.pymanager.py 3.3 主程序代码main.py 3.4 运行结果 四、总结 Python模块和包…

Apifox 「定时任务」操作指南,解锁自动化测试的新利器

定时任务是按照预设时间自动执行的任务&#xff0c;它可以有效解决一些常见问题&#xff0c;比如频繁执行的回归测试和大规模的接口测试&#xff0c;这些任务需要在固定时间点或间隔周期内自动运行&#xff0c;以确保软件的持续集成和持续交付过程中的稳定性和可靠性。通过使用…

计算机网络34——Windows内存管理

1、计算机体系结构 2、内存管理 分为连续分配管理和非连续分配管理 在块内存在的未使用空间叫内部碎片&#xff0c;在块外存在的未使用空间叫外部碎片 固定分区分配可能出现内部碎片&#xff0c;动态分区分配可能出现外部碎片 3、逻辑地址和实际地址的互相转换 4、缺页中断 …

微信支付商户 - 如何开通商家转账到零钱

商家转账到零钱功能的快速开通&#xff0c;需要商家遵循一系列步骤并确保所有条件符合微信支付的要求。以下是一些关键步骤和注意事项&#xff0c;以确保商家可以最快开通该功能&#xff1a; 一、确认申请资格 1. 公司性质&#xff1a;确保申请主体为公司性质&#xff08;有限…

【Docker】安装全流程与配置完整镜像源(可安装 nginx)

目录 一、卸载历史版本&#xff08;选&#xff09;二、配置 yum 源三、安装 docker四、配置 docker 镜像源加速&#xff08;选、强烈建议&#xff09;4.1 配置阿里镜像加速4.2 配置其他镜像源 五、启动 docker参考文章与视频 本文基于 Linux - CentOS 7 操作系统。 一、卸载历史…

Unity3D入门(二) :Unity3D实现视角的丝滑过渡切换

1. 前言 上篇文章&#xff0c;我们已经初步了解了Unity3D&#xff0c;并新建并运行起来了一个项目&#xff0c;使相机视角自动围绕着立方体旋转。 这篇文章&#xff0c;我们来讲一下Unity3D怎么过渡地切换视角。 我们继续是我上篇文章中的项目&#xff0c;但是需要向把Camera…

TFT-LCD显示屏(1.8寸 STM32)

目录 一、介绍 二、传感器原理 1.原理图 2.引脚描述 3.工作原理&#xff1a;TFT-LCD色彩空间 三、程序设计 main.c文件 lcd.h文件 lcd.c文件 四、实验效果 五、资料获取 项目分享 一、介绍 TFT-LCD&#xff0c;全称Thin Film Transistor Liquid Crystal Display&a…

Golang | Leetcode Golang题解之第409题最长回文串

题目&#xff1a; 题解&#xff1a; func longestPalindrome(s string) int {mp : map[byte]int{}for i : 0; i < len(s); i {mp[s[i]]}res : 0for _, v : range mp {if v&1 1 {res v - 1} else {res v}}if res<len(s) {res}return res }

C++笔记21•C++11的新特性•

相比于 C98/03&#xff0c;C11则带来了数量可观的变化&#xff0c;其中包含了约140个新特性&#xff0c;以及对C03标准中约600个缺陷的修正&#xff0c;这使得C11更像是从C98/03中孕育出的一种新语言。相比较而言&#xff0c;C11能更好地用于系统开发和库开发、语法更加泛华和简…

如何合并pdf文件,四款软件,三步搞定!

在数字化办公的浪潮中&#xff0c;PDF文档因其跨平台兼容性和安全性&#xff0c;成为了我们日常工作中不可或缺的一部分。然而&#xff0c;面对多个PDF文件需要整合成一个文件时&#xff0c;不少小伙伴可能会感到头疼。别担心&#xff0c;今天我们就来揭秘四款高效PDF合并软件&…

演示:基于WPF的DrawingVisual开发的Chart图表和表格绘制

一、目的&#xff1a;基于WPF的DrawingVisual开发的Chart图表和表格绘制 二、预览 钻井井轨迹表格数据演示示例&#xff08;应用Table布局&#xff0c;模拟井轨迹深度的绘制&#xff09; 饼图表格数据演示示例&#xff08;应用Table布局&#xff0c;模拟多个饼状图组合显示&am…

尚品汇-秒杀商品定时任务存入缓存、Redis发布订阅实现状态位(五十一)

目录&#xff1a; &#xff08;1&#xff09;秒杀业务分析 &#xff08;2&#xff09;搭建秒杀模块 &#xff08;3&#xff09;秒杀商品导入缓存 &#xff08;4&#xff09;redis发布与订阅实现 &#xff08;1&#xff09;秒杀业务分析 需求分析 所谓“秒杀”&#xff0…