jdbc实现批量给多个表中更新数据(解析Excel表数据插入到数据库中)

大家好,我是雄雄,欢迎关注微信公众号:雄雄的小课堂

前言

现在是:2022年5月19日08:01:51

今天遇到了个这样的需求,解析excel表中的数据,以JDBC的方式,将数据批量更新至不同的数据表中。注意,更新指的是:如果数据表中有该条记录,则更新操作,如果没有,则新增操作。

实现思路

解析Excel,直接写了个工具类,先看一下代码,在做说明:

	 /*** 解析excel表格,每行数据,分别插入到两个表中,巡查的视频表* 已经执行完成* 2022年5月12日21:22:01** ↓执行情况如下↓* 一共有这么多行:88* **************开始执行************** *************执行完毕******************集合的长度是:88* equipment表的添加情况88* disanfangvedio表的添加情况88**/public static void updateBaseEquipmentAndBaseDiSanFangVedio(){String excelPath = System.getProperty("user.dir") + "/ruoyi-admin/src/main/java/zhengshiflowstuisong519.xlsx";try {//String encoding = "GBK";File excel = new File(excelPath);//判断文件是否存在if (excel.isFile() && excel.exists()) {//.是特殊字符,需要转义!!!!!String[] split = excel.getName().split("\\.");Workbook wb;//根据文件后缀(xls/xlsx)进行判断if ("xls".equals(split[1])) {//文件流对象FileInputStream fis = new FileInputStream(excel);wb = new HSSFWorkbook(fis);} else if ("xlsx".equals(split[1])) {wb = new XSSFWorkbook(excel);} else {System.out.println("文件类型错误!");return;}//开始解析// 读取sheet 0Sheet sheet = wb.getSheetAt(0);//第一行是列名,所以不读int firstRowIndex = sheet.getFirstRowNum() + 1;int lastRowIndex = sheet.getLastRowNum();System.out.println("一共有这么多行:"+lastRowIndex);System.out.println("**************开始执行**************");//将信息放在集合里面,添加的时候好处理List<EquipmentAndDiSanFangVedioEntity> equipmentAndDiSanFangVedioEntityListList = new ArrayList<>();//遍历行for (int rIndex = firstRowIndex; rIndex <=lastRowIndex; rIndex++) {//初始化对象EquipmentAndDiSanFangVedioEntity equipmentAndDiSanFangVedioEntity = new EquipmentAndDiSanFangVedioEntity();BaseEquipment baseEquipment = new BaseEquipment();BaseDisanfangvedio baseDisanfangvedio = new BaseDisanfangvedio();//不会重复吧String uuid = IdUtils.fastSimpleUUID();System.out.print(rIndex+":");Row row = sheet.getRow(rIndex);if (row != null) {DataFormatter dataFormatter = new DataFormatter();//regionkeyCell cell_regionkey = row.getCell(0);double cell_regionkey_double = Double.parseDouble(cell_regionkey.toString());Long regionkey = (long)cell_regionkey_double;baseEquipment.setDeptId(regionkey);baseDisanfangvedio.setRegionkey(regionkey);baseDisanfangvedio.setVenueId(regionkey.toString());//equipment_nameCell cell_equipment_name = row.getCell(1);String equipment_name =dataFormatter.formatCellValue(cell_equipment_name);baseEquipment.setEquipmentCode(equipment_name);baseDisanfangvedio.setEquipmentName(equipment_name);//province_idCell cell_province_id = row.getCell(2);String province_id =dataFormatter.formatCellValue(cell_province_id);baseDisanfangvedio.setProvinceId(province_id);//city_idCell cell_city_id = row.getCell(3);String city_id =dataFormatter.formatCellValue(cell_city_id);baseDisanfangvedio.setCityId(city_id);//district_idCell cell_district_id = row.getCell(4);String district_id =dataFormatter.formatCellValue(cell_district_id);baseDisanfangvedio.setDistrictId(district_id);//venue_idCell cell_venue_id = row.getCell(5);String venue_id =dataFormatter.formatCellValue(cell_venue_id);//摄像机名称Cell cell_openArea = row.getCell(6);String openArea =dataFormatter.formatCellValue(cell_openArea);baseEquipment.setEquipmentName(openArea);baseEquipment.setLocation(openArea);//real_time_video_addressCell cell_real_time_video_address = row.getCell(7);String real_time_video_address =dataFormatter.formatCellValue(cell_real_time_video_address);baseDisanfangvedio.setRealTimeVideoAddress(real_time_video_address);baseEquipment.setBrandId("宇视");baseEquipment.setTypeId("1");baseEquipment.setIpAddress(uuid);baseEquipment.setStateId("0");baseEquipment.setOnlineDate(new Date());baseEquipment.setIsCoreArea(1);baseEquipment.setIsExamine("0");baseDisanfangvedio.setDeviceId(uuid);baseDisanfangvedio.setCreateTime(new Date());equipmentAndDiSanFangVedioEntity.setBaseEquipment(baseEquipment);equipmentAndDiSanFangVedioEntity.setBaseDisanfangvedio(baseDisanfangvedio);//添加到集合里面equipmentAndDiSanFangVedioEntityListList.add(equipmentAndDiSanFangVedioEntity);}}System.out.println("*************执行完毕******************\n集合的长度是:"+equipmentAndDiSanFangVedioEntityListList.size());System.out.println("请稍等…………");System.out.println("正在插入到数据库…………");System.out.println("再等等…………");//调用更新的方法ZhiXingMysqlNew zhiXingMysqlNew = new ZhiXingMysqlNew();//暂时先注释掉,怕误调用此方法 2022年5月18日17:05:28zhiXingMysqlNew.updateBaseEquipmentAndBaseDiSanFangVedio(equipmentAndDiSanFangVedioEntityListList);System.out.println("插入完毕!!!");} else {System.out.println("找不到指定的文件");}} catch (Exception e) {e.printStackTrace();}}

代码说明

  • 此类专门用作解析Excel文件
  • 将每列需要用到的信息,解析之后放在集合中,更新时需要用
  • 调用更新的方法进行更新操作

更新操作

这个方法是专门用来更新操作的,实现思路:

  1. 根据指定的条件查询数据表中该记录是否存在,必须是唯一的,可以多个条件组合
  2. 如果有记录,则执行更新操作
  3. 如果没有记录,则执行添加操作
  4. 均采用JDBC批量更新的方式,addBatchexecuteBatchclearBatch
  5. 最后关闭流

代码如下:

	/*** 更新base_equipment表和base_disanfangvedio表* 1.先去视频表里面查询,是否有记录* 2.如果有记录,则更新视频表* 3.如果没有记录,则两个表都插入一条记录* 4.判断地址是否为空,如果是空,则值给设备表中插入数据* ** @param equipmentAndDiSanFangVedioEntityList*/public void updateBaseEquipmentAndBaseDiSanFangVedio(List<EquipmentAndDiSanFangVedioEntity> equipmentAndDiSanFangVedioEntityList) {Connection connection = connection = getConnection();//添加PreparedStatement pStatementEquInsert = null;PreparedStatement pStatementDsfInsert = null;//修改PreparedStatement pStatementEquUpdate = null;PreparedStatement pStatementDsfUpdate = null;//查询PreparedStatement pStatementEquipmentSelect = null;ResultSet rs = null;try {//先根据场馆id和点位名称查询信息String sqlEquipmentSelect = "SELECT * FROM base_equipment WHERE dept_id = ? AND equipment_name =  ?";//新增的sql语句String sqlEquipmentInsert = "  INSERT INTO base_equipment \n" +"( equipment_code, equipment_name,dept_id, \n" +"location, brand_id, type_id, ip_address, \n" +"state_id, \n" +"online_date,  is_core_area,is_examine ) \n" +" VALUES ( ?,?,?,?,?,?,?,?,?,?,?)";String sqlBaseDisanFangVedioInsert = " INSERT INTO base_disanfangvedio \n" +"( regionkey, equipment_name, province_id,\n" +" city_id, district_id, venue_id, real_time_video_address, \n" +" device_id, create_time) \n" +" VALUES (?, ?,?, ?, ?, ?, ?, ?, ?)";//修改的sql语句String sqlEquipmentUpdate = " UPDATE base_equipment SET equipment_code = ?, equipment_name = ?, " +"dept_id = ?, location = ?, brand_id = ?, type_id = ?, state_id = ?, " +"online_date = ?, is_core_area = ?, is_examine = ? WHERE ip_address = ?";String sqlBaseDisanFangVedioUpdate = " UPDATE base_disanfangvedio SET regionkey = ?, " +"equipment_name = ?, province_id = ?, city_id = ?, district_id = ?, " +"venue_id = ?, real_time_video_address = ?, create_time = ? " +"WHERE device_id = ?";SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//添加的pStatementEquInsert = connection.prepareStatement(sqlEquipmentInsert);pStatementDsfInsert = connection.prepareStatement(sqlBaseDisanFangVedioInsert);//修改的pStatementEquUpdate = connection.prepareStatement(sqlEquipmentUpdate);pStatementDsfUpdate = connection.prepareStatement(sqlBaseDisanFangVedioUpdate);//查询的pStatementEquipmentSelect = connection.prepareStatement(sqlEquipmentSelect);//批量插入数据for (EquipmentAndDiSanFangVedioEntity equipmentAndDiSanFangVedioEntity : equipmentAndDiSanFangVedioEntityList) {//先根据场馆id和点位名称查询信息pStatementEquipmentSelect.setObject(1, equipmentAndDiSanFangVedioEntity.getBaseEquipment().getDeptId());pStatementEquipmentSelect.setObject(2, equipmentAndDiSanFangVedioEntity.getBaseEquipment().getEquipmentName());rs = pStatementEquipmentSelect.executeQuery();if (rs.next()) {//找到了结果了,说明已经存在了,不需要插入,需要更新//获取唯一标识String ipAddress = rs.getString("ip_address");//更新//equipment表pStatementEquUpdate.setString(1, equipmentAndDiSanFangVedioEntity.getBaseEquipment().getEquipmentCode());pStatementEquUpdate.setString(2, equipmentAndDiSanFangVedioEntity.getBaseEquipment().getEquipmentName());pStatementEquUpdate.setLong(3, equipmentAndDiSanFangVedioEntity.getBaseEquipment().getDeptId());pStatementEquUpdate.setString(4, equipmentAndDiSanFangVedioEntity.getBaseEquipment().getLocation());pStatementEquUpdate.setString(5, equipmentAndDiSanFangVedioEntity.getBaseEquipment().getBrandId());pStatementEquUpdate.setString(6, equipmentAndDiSanFangVedioEntity.getBaseEquipment().getTypeId());pStatementEquUpdate.setString(7, equipmentAndDiSanFangVedioEntity.getBaseEquipment().getStateId());pStatementEquUpdate.setString(8, simpleDateFormat.format(equipmentAndDiSanFangVedioEntity.getBaseEquipment().getOnlineDate()));pStatementEquUpdate.setInt(9, equipmentAndDiSanFangVedioEntity.getBaseEquipment().getIsCoreArea());pStatementEquUpdate.setString(10, equipmentAndDiSanFangVedioEntity.getBaseEquipment().getIsExamine());pStatementEquUpdate.setString(11, ipAddress);//disanfangvedio表pStatementDsfUpdate.setLong(1, equipmentAndDiSanFangVedioEntity.getBaseDisanfangvedio().getRegionkey());pStatementDsfUpdate.setString(2, equipmentAndDiSanFangVedioEntity.getBaseDisanfangvedio().getEquipmentName());pStatementDsfUpdate.setString(3, equipmentAndDiSanFangVedioEntity.getBaseDisanfangvedio().getProvinceId());pStatementDsfUpdate.setString(4, equipmentAndDiSanFangVedioEntity.getBaseDisanfangvedio().getCityId());pStatementDsfUpdate.setString(5, equipmentAndDiSanFangVedioEntity.getBaseDisanfangvedio().getDistrictId());pStatementDsfUpdate.setString(6, equipmentAndDiSanFangVedioEntity.getBaseDisanfangvedio().getVenueId());pStatementDsfUpdate.setString(7, equipmentAndDiSanFangVedioEntity.getBaseDisanfangvedio().getRealTimeVideoAddress());pStatementDsfUpdate.setString(8, simpleDateFormat.format(equipmentAndDiSanFangVedioEntity.getBaseDisanfangvedio().getCreateTime()));pStatementDsfUpdate.setString(9, ipAddress);//批量修改pStatementEquUpdate.addBatch();pStatementDsfUpdate.addBatch();} else {//没有找到结果,插入数据//equipment表pStatementEquInsert.setString(1, equipmentAndDiSanFangVedioEntity.getBaseEquipment().getEquipmentCode());pStatementEquInsert.setString(2, equipmentAndDiSanFangVedioEntity.getBaseEquipment().getEquipmentName());pStatementEquInsert.setLong(3, equipmentAndDiSanFangVedioEntity.getBaseEquipment().getDeptId());pStatementEquInsert.setString(4, equipmentAndDiSanFangVedioEntity.getBaseEquipment().getLocation());pStatementEquInsert.setString(5, equipmentAndDiSanFangVedioEntity.getBaseEquipment().getBrandId());pStatementEquInsert.setString(6, equipmentAndDiSanFangVedioEntity.getBaseEquipment().getTypeId());pStatementEquInsert.setString(7, equipmentAndDiSanFangVedioEntity.getBaseEquipment().getIpAddress());pStatementEquInsert.setString(8, equipmentAndDiSanFangVedioEntity.getBaseEquipment().getStateId());pStatementEquInsert.setString(9, simpleDateFormat.format(equipmentAndDiSanFangVedioEntity.getBaseEquipment().getOnlineDate()));pStatementEquInsert.setInt(10, equipmentAndDiSanFangVedioEntity.getBaseEquipment().getIsCoreArea());pStatementEquInsert.setString(11, equipmentAndDiSanFangVedioEntity.getBaseEquipment().getIsExamine());//批量添加pStatementEquInsert.addBatch();//判断视频地址是否为空//  if(Strings.isNotBlank( equipmentAndDiSanFangVedioEntity.getBaseDisanfangvedio().getRealTimeVideoAddress())){//不为空的话,需要给视频表里面维护数据//disanfangvedio表pStatementDsfInsert.setLong(1, equipmentAndDiSanFangVedioEntity.getBaseDisanfangvedio().getRegionkey());pStatementDsfInsert.setString(2, equipmentAndDiSanFangVedioEntity.getBaseDisanfangvedio().getEquipmentName());pStatementDsfInsert.setString(3, equipmentAndDiSanFangVedioEntity.getBaseDisanfangvedio().getProvinceId());pStatementDsfInsert.setString(4, equipmentAndDiSanFangVedioEntity.getBaseDisanfangvedio().getCityId());pStatementDsfInsert.setString(5, equipmentAndDiSanFangVedioEntity.getBaseDisanfangvedio().getDistrictId());pStatementDsfInsert.setString(6, equipmentAndDiSanFangVedioEntity.getBaseDisanfangvedio().getVenueId());pStatementDsfInsert.setString(7, equipmentAndDiSanFangVedioEntity.getBaseDisanfangvedio().getRealTimeVideoAddress());pStatementDsfInsert.setString(8, equipmentAndDiSanFangVedioEntity.getBaseDisanfangvedio().getDeviceId());pStatementDsfInsert.setString(9, simpleDateFormat.format(equipmentAndDiSanFangVedioEntity.getBaseDisanfangvedio().getCreateTime()));//批量添加pStatementDsfInsert.addBatch();// }}}//批量添加操作int[] pStatementEquCounts = pStatementEquInsert.executeBatch();int[] pStatementDsfCounts = pStatementDsfInsert.executeBatch();//批量修改操作int[] pStatementEquUpdateCounts = pStatementEquUpdate.executeBatch();int[] pStatementDsfUpdateCounts = pStatementDsfUpdate.executeBatch();System.out.println("批量添加的情况:equipment表:" + pStatementEquCounts.length+",disanfangvedio表:"+pStatementDsfCounts.length);System.out.println("批量修改的情况:equipment表:" + pStatementEquUpdateCounts.length+",disanfangvedio表:"+pStatementDsfUpdateCounts.length);//批量clearpStatementEquInsert.clearBatch();pStatementDsfInsert.clearBatch();pStatementEquUpdate.clearBatch();pStatementDsfUpdate.clearBatch();} catch (Exception e) {e.printStackTrace();} finally {closeResultSet(rs);closePreparedStatement(pStatementEquInsert);closePreparedStatement(pStatementDsfInsert);closePreparedStatement(pStatementEquUpdate);closePreparedStatement(pStatementDsfUpdate);closePreparedStatement(pStatementEquipmentSelect);closeConnection(connection);}}

注意事项

  1. 类似这种直接操作数据表的,一定要先把表备份一下
  2. 安全起见,excel表格中先只保留一行数据,解析导入没有问题的话,在导入整个表
  3. 一定要-先备份,先备份,先备份!!!

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

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

相关文章

CF559C-Gerald and Giant Chess【计数类dp】

正题 上不了Codeforces&#xff0c;就用洛谷了 评测记录:https://www.luogu.org/recordnew/lists?uid52918&pidCF559C 题目大意 H∗WH∗W的棋盘上有一个卒从(1,1)走到(H,W)&#xff0c;有些点不能走&#xff0c;求方案总数。 解题思路 首先如果没有障碍走到(i,j)方案数…

.Net Core 全局配置读取管理方法 ConfigurationManager

最近在学习.Net Core的过程中&#xff0c;发现.Net Framework中常用的ConfigurationManager在Core中竟然被干掉了。 也能理解。Core中使用的配置文件全是Json&#xff0c;不像Framework使用的XML&#xff0c;暂时不支持也是能理解的&#xff0c;但是毕竟全局配置文件这种东西还…

Http 持久连接与 HttpClient 连接池

转载自 Http 持久连接与 HttpClient 连接池 一、背景 HTTP协议是无状态的协议&#xff0c;即每一次请求都是互相独立的。因此它的最初实现是&#xff0c;每一个http请求都会打开一个tcp socket连接&#xff0c;当交互完毕后会关闭这个连接。 HTTP协议是全双工的协议&#x…

jdbc解析excel文件,批量插入数据至库中

“大家好&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号&#xff1a;雄雄的小课堂”前言现在是&#xff1a;2022年5月20日09:32:38今天遇到了个这样的需求&#xff0c;解析excel表中的数据&#xff0c;以JDBC的方式&#xff0c;将数据批量更新至不同的数据表中。注意&…

线程2

public class test{/*** 测试延迟继承* param args*/public static void main(String[] args) {Cat catnew Cat();cat.start();//启动线程&#xff0c;会导致run函数的运行Dog dognew Dog();//创建一个线程对象Thread tnew Thread(dog);t.start();}} //继承Thread创建线程 clas…

.NET及.NET Core系统架构

.NET 官方架构指南 Microservices and Docker Containers Web Applications with ASP.NET 官网地址&#xff1a;https://www.microsoft.com/net/learn/architecture 三层及多层架构 Multitier Architecture ASP.NET N-Tier Architecture Schema Visual Studio N-Tier Examp…

POJ3208-Apocalypse Someday【数位dp】

正题 题目链接:http://poj.org/problem?id3208 题目大意 求第X个有3个连续的6的数。 解题思路 用fi,j(j<3)fi,j(j<3)表示i位&#xff0c;已经有j个6的方案总数。然后fi,3fi,3表示i位的魔鬼数的总数。 然后动态转移方程。 fi,09∗(fi−1,0fi−1,1fi−1,2)fi,09∗(fi…

Spring Boot 自动配置的 “魔法” 是如何实现的?

转载自 Spring Boot 自动配置的 “魔法” 是如何实现的&#xff1f; Spring Boot是Spring旗下众多的子项目之一&#xff0c;其理念是约定优于配置&#xff0c;它通过实现了自动配置&#xff08;大多数用户平时习惯设置的配置作为默认配置&#xff09;的功能来为用户快速构建出…

for循环(一)

利用for循环打出一百句HelloWorld #include<stdio.h>main(){int i;for(i0;i<100;i){printf("HelloWorld\n");} } ![在这里插入图片描述](https://img-blog.csdnimg.cn/20190324224126588.png?x-oss-processimage/watermark,type_ZmFuZ3poZW5naGVpdGk,sha…

解决vue登录信息不及时更新问题

大家好&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号&#xff1a;雄雄的小课堂 前言 现在是&#xff1a;2022年5月20日09:59:34 前面写过一篇文章&#xff0c;基于bladex框架实现的模拟登录&#xff0c;后来在测试的过程中发现了个问题&#xff0c;即A系统在跳转到本系…

学习ASP.NET Core,怎能不了解请求处理管道[2]: 服务器在管道中的“龙头”地位

ASP.NET Core管道由注册的服务器和一系列中间件构成。我们在上一篇中深入剖析了中间件&#xff0c;现在我们来了解一下服务器。服务器是ASP .NET Core管道的第一个节点&#xff0c;它负责完整请求的监听和接收&#xff0c;最终对请求的响应同样也由它完成。[本文已经同步到《AS…

Ch3101-阶乘分解【数论,质因数分解】

正题 题目链接:http://contest-hunter.org:83/contest/0x30%E3%80%8C%E6%95%B0%E5%AD%A6%E7%9F%A5%E8%AF%86%E3%80%8D%E4%BE%8B%E9%A2%98/3101%20%E9%98%B6%E4%B9%98%E5%88%86%E8%A7%A3 题目大意 质因数分解n!n!的阶乘。 解题思路 很简单的数学题&#xff0c;将1∼n1∼n全部…

for循环(二)

利用for循环按规律打出星星 #include<stdio.h>main(){int i,j;for(i0;i<10;i){for(j0;j<i;j){printf(" *"); }printf("\n");} }

接口方法上的注解无法被@Aspect声明的切面拦截的原因分析

转载自 接口方法上的注解无法被Aspect声明的切面拦截的原因分析 前言 在Spring中使用MyBatis的Mapper接口自动生成时&#xff0c;用一个自定义的注解标记在Mapper接口的方法中&#xff0c;再利用Aspect定义一个切面&#xff0c;拦截这个注解以记录日志或者执行时长。但是惊奇…

springboot实现用户统一认证、管理(单点登录)

大家好&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号&#xff1a;雄雄的小课堂 前言 现在是&#xff1a;2022年5月25日13:44:16 最近和模拟登录杠上了&#xff0c;这不&#xff0c;又来了个需求&#xff0c;还是以这个技术点入手的。 需求大概是这样的&#xff1a;为了…

学习ASP.NET Core,怎能不了解请求处理管道[1]: 中间件究竟是个什么东西?

ASP.NET Core管道虽然在结构组成上显得非常简单&#xff0c;但是在具体实现上却涉及到太多的对象&#xff0c;所以我们在 “通过重建Hosting系统理解HTTP请求在ASP.NET Core管道中的处理流程”&#xff08;上篇、中篇、下篇&#xff09; 中围绕着一个经过极度简化的模拟管道讲述…

POJ2689-Prime Distance【质数,数论】

正题 题目链接:http://poj.org/problem?id2689 题目大意 求闭区间[L,R][L,R]中相邻的最远和最近的两个质数。 解题思路 我们可以用前R−−√个质因子筛这个区间内的质数R个质因子筛这个区间内的质数解题思路 #include<cstdio> #include<algorithm> #include&l…

for循环(三)

利用for循环打出乘法口诀表 #include<stdio.h>main(){int i,j,k;for(i1;i<10;i){for(j1;j<i1;j){printf("%d*%d%d\t",i,j,ki*j); }printf("\n");} } ![在这里插入图片描述](https://img-blog.csdnimg.cn/20190324224732816.png?x-oss-proce…

springboot实现用户统一认证、管理

“大家好&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号&#xff1a;雄雄的小课堂”前言现在是&#xff1a;2022年5月25日13:44:16最近和模拟登录杠上了&#xff0c;这不&#xff0c;又来了个需求&#xff0c;还是以这个技术点入手的。需求大概是这样的&#xff1a;为了统…

Mybatis 使用的 9 种设计模式,真是太有用了

转载自 Mybatis 使用的 9 种设计模式&#xff0c;真是太有用了 虽然我们都知道有26个设计模式&#xff0c;但是大多停留在概念层面&#xff0c;真实开发中很少遇到&#xff0c;Mybatis源码中使用了大量的设计模式&#xff0c;阅读源码并观察设计模式在其中的应用&#xff0c;…