当前位置: 首页 > ops >正文

java,通过SqlSessionFactory实现动态表明的插入和查询(适用于一个版本一个表的场景)

1,测试实体类

package org.springblade.sample.test;import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;/*** @Author: 肖扬* @CreateTime: 2025-09-05* @Description: SqlSessionFactoryTest测试* @Version: 1.0*/
@Data
@TableName("session_factory_pojo")
public class SessionFactoryPojo {private Long id;private String name;private String age;
}

2,测试Mapper类

package org.springblade.sample.test;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springblade.sample.entity.PangolinCsvData;import java.util.List;@Mapper
public interface SessionFactoryMapper extends BaseMapper<SessionFactoryPojo> {void insertBatch(@Param("list") List<PangolinCsvData> list);
}

3,测试Xml类

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.springblade.sample.test.SessionFactoryMapper"><insert id="insertBatch">INSERT INTO $TABLE_NAME$ (id,name,age) VALUES<foreach collection="list" item="item" index="index" separator=",">(#{item.id},#{item.name},#{item.age})</foreach></insert>
</mapper>

4,工具类

package org.springblade.sample.utils;import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.binding.MapperMethod;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.ParameterMapping;
import org.springblade.core.tool.utils.BeanUtil;
import org.springblade.core.tool.utils.StringUtil;import java.sql.Timestamp;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;/*** @Author: 肖扬* @CreateTime: 2025-09-05* @Description: MyBatis BoundSql 转可执行 SQL 工具类(支持 list、对象、map)* @Version: 2.0*/
@Slf4j
@UtilityClass
public class SqlBuilderUtil {private final Pattern LIST_PARAM_PATTERN = Pattern.compile("__frch_item_(\\d+)\\.(.+)");/*** 将 BoundSql 转换为可执行 SQL** @param boundSql    MyBatis BoundSql* @param paramObject Mapper 参数(支持 list、单对象、Map)* @param ListKey     参数key* @return 可执行 SQL 字符串*/public String buildExecutableSql(BoundSql boundSql, Object paramObject, String ListKey) {String sql = boundSql.getSql();List<ParameterMapping> paramMappings = boundSql.getParameterMappings();if (paramMappings == null || paramMappings.isEmpty()) {return sql;}StringBuilder resultSql = new StringBuilder(sql);for (ParameterMapping p : paramMappings) {String paramName = p.getProperty();Object paramValue = resolveParamValue(paramName, paramObject, ListKey);String replacement = formatSqlValue(paramValue);// 替换第一个 ? 为实际值int qIndex = resultSql.indexOf("?");if (qIndex >= 0) {resultSql.replace(qIndex, qIndex + 1, replacement);}}return resultSql.toString();}/*** 根据参数名解析参数值,支持 list / Map / 普通对象*/private Object resolveParamValue(String paramName, Object paramObject, String listKey) {if (paramObject == null) {return null;}// 1. 支持 list 参数(批量 insert/update)if (paramObject instanceof MapperMethod.ParamMap) {MapperMethod.ParamMap<?> paramMap = (MapperMethod.ParamMap<?>) paramObject;// list 参数if (StringUtil.isNotBlank(listKey) && paramMap.containsKey(listKey)) {List<?> listObj = (List<?>) paramMap.get(listKey);Matcher matcher = LIST_PARAM_PATTERN.matcher(paramName);if (matcher.matches()) {int index = Integer.parseInt(matcher.group(1));String property = matcher.group(2);if (listObj != null && index < listObj.size()) {return BeanUtil.toMap(listObj.get(index)).get(property);}}}// 其他 Map 参数(#{xxx} 这种)if (paramMap.containsKey(paramName)) {return paramMap.get(paramName);}}// 2. 直接传入 Mapif (paramObject instanceof Map) {return ((Map<?, ?>) paramObject).get(paramName);}// 3. 普通对象,通过反射取属性Map<String, Object> objMap = BeanUtil.toMap(paramObject);return objMap.get(paramName);}/*** 参数值转 SQL 字符串*/private String formatSqlValue(Object value) {if (value == null) {return "NULL";}if (value instanceof String) {// 简单转义单引号return "'" + ((String) value).replace("'", "''") + "'";}if (value instanceof Number) {return String.valueOf(value);}if (value instanceof Date) {return "'" + new Timestamp(((Date) value).getTime()) + "'";}return "'" + value.toString().replace("'", "''") + "'";}
}

5,测试Controller

package org.springblade.sample.test;import io.swagger.annotations.Api;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.binding.MapperMethod;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springblade.core.tool.utils.BeanUtil;
import org.springblade.sample.utils.SqlBuilderUtil;
import org.springblade.scheduled.exception.ScheduledException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;/*** @Author: 肖扬* @CreateTime: 2025-09-05* @Description: 测试SqlSessionFactoryTest* @Version: 1.0*/
@RequiredArgsConstructor
@RestController
@RequestMapping("/scheduled/")
@Api(tags = "SqlSessionFactoryTest")
@Slf4j
public class SessionFactoryTestController {private final JdbcTemplate jdbcTemplate;private final SqlSessionFactory sqlSessionFactory;private final PlatformTransactionManager transactionManager;@GetMapping( "testSessionFactory")public void testSqlSessionFactory() {List<SessionFactoryPojo> list = new ArrayList<>();list.add(new SessionFactoryPojo(2L, "李四", "25"));String tableName = "session_factory_pojo";String mapperMethod = "org.springblade.sample.test.SessionFactoryMapper.insertBatch";MapperMethod.ParamMap<List<?>> paramMap = new MapperMethod.ParamMap<>();paramMap.put("list",list );//开启事务DefaultTransactionDefinition def = new DefaultTransactionDefinition();def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);TransactionStatus status = transactionManager.getTransaction(def);try (SqlSession sqlSession = sqlSessionFactory.openSession()) {Configuration configuration = sqlSession.getConfiguration();MappedStatement mappedStatement = configuration.getMappedStatement(mapperMethod);BoundSql boundSql = mappedStatement.getBoundSql(paramMap);//buildExecutableSql的listKey和paramMap的key和insertBatch的参数名称和一致String sql = SqlBuilderUtil.buildExecutableSql(boundSql, paramMap, "list");sql = sql.replace("$TABLE_NAME$", tableName);log.info("sql:{}", sql);jdbcTemplate.execute(sql);// 提交事务transactionManager.commit(status);}catch (Exception e){log.error("createTidalTask occurred exception: {}", e.getMessage(), e);// 发生异常时回滚事务transactionManager.rollback(status);throw new ScheduledException("任务执行失败!");}}
}

http://www.xdnf.cn/news/19997.html

相关文章:

  • c51串口通信原理及实操
  • 进程和线程创建销毁时mutex死锁问题分析
  • 神经网络之深入理解偏置
  • Go语言实战案例- 命令行参数解析器
  • Gin + Viper 实现配置读取与热加载
  • swing笔记
  • 【Flutter】flutter_local_notifications并发下载任务通知实践
  • 深度学习基础概念【持续更新】
  • 前端安全防护深度实践:从XSS到供应链攻击的全面防御
  • JAiRouter 配置文件重构纪实 ——基于单一职责原则的模块化拆分与内聚性提升
  • 消费品企业客户数据分散?CRM 系统来整合
  • Python包管理工具全对比:pip、conda、Poetry、uv、Flit深度解析
  • mac怎么安装uv工具
  • CT影像寻找皮肤轮廓预处理
  • 一天一个强大的黑科技网站第1期~一键抠图神器!设计师必备!分分钟扣100张图!
  • 基于STM32设计的激光充电控制系统(华为云IOT)_277
  • Flutter的三棵树
  • 【STM32外设】DAC
  • Big Data Analysis
  • 某头部能源集团“数据治理”到“数智应用”跃迁案例剖析
  • Ubuntu中使用nginx-rtmp-module实现视频点播
  • mac 安装 nginx
  • Day36 TCP客户端编程 HTTP协议解析 获取实时天气信息
  • 如何选择适合的实验室铸铁地板和铸铁试验平板?专业人士帮助指南
  • 【开题答辩全过程】以 基于Android的点餐系统为例,包含答辩的问题和答案
  • 《sklearn机器学习——多标签排序指标》
  • Conda 使用py环境隔离
  • 新后端漏洞(上)- H2 Database Console 未授权访问
  • 高级RAG策略学习(四)——上下文窗口增强检索RAG
  • 耐达讯自动化RS485与Profinet双向奔赴,伺服驱动器连接“稳稳拿捏”