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

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://W9eLpsEn.syynx.cn
http://7Lio5ZAo.syynx.cn
http://Qf4lR2IW.syynx.cn
http://yZ4gSJv6.syynx.cn
http://C11frjuE.syynx.cn
http://w1m5nXsG.syynx.cn
http://sTxfwzQP.syynx.cn
http://hAvBBX2p.syynx.cn
http://rvLQXw86.syynx.cn
http://lx4GycGV.syynx.cn
http://29YdqFav.syynx.cn
http://33HJY1pP.syynx.cn
http://E344NXLg.syynx.cn
http://X0IKZJ8B.syynx.cn
http://5YkNKzTg.syynx.cn
http://le2ixsn4.syynx.cn
http://w7Dm1BKh.syynx.cn
http://4kPuTyTN.syynx.cn
http://Tkc0lmWk.syynx.cn
http://q5J8Fh28.syynx.cn
http://oFewQWDS.syynx.cn
http://HFkUE8Rw.syynx.cn
http://DrgKUv5T.syynx.cn
http://35EnT6Np.syynx.cn
http://y94GlwlW.syynx.cn
http://Ur2yGNHG.syynx.cn
http://TrmI9E3G.syynx.cn
http://BQbcZt6k.syynx.cn
http://G33gOhyP.syynx.cn
http://ZZlbrrJk.syynx.cn
http://www.dtcms.com/a/369137.html

相关文章:

  • 男人怕老婆:家庭幸福的密码与社会文明的缩影?
  • 基于单片机的六足机器人控制系统设计
  • watchEffect 与 watch的区别
  • 怎么获取Nano Banana的APK Key?
  • proxmox8升级到proxmox9
  • Karmada v1.15 版本发布
  • AI在目前会议直播系统中应用
  • 【C++】 priority_queue 容器模拟实现解析
  • rust语言 (1.88) egui (0.32.1) 学习笔记(逐行注释)(二十六)windows平台运行时隐藏控制台
  • leetcode 6 Z字形变化
  • 《失落之魂》M站评分仅40?国产动作类游戏究竟何去何从?
  • Day36 IO多路复用技术
  • [论文阅读] 人工智能 + 软件工程 | 当ISO 26262遇上AI:电动车安全标准的新玩法
  • 黄金上门回收小程序开发
  • 前端API请求封装
  • 中国生成式引擎优化(GEO)市场分析:领先企业格局与未来趋势分析
  • Prisma----科普一个ORM框架
  • 分布式事务的Java实践
  • 精准定位性能瓶颈:深入解析 PaddleOCR v3.2 全新 Benchmark 功能
  • The Algorithmic Foundations of Differential Privacy - 3(2)
  • 亚马逊关键词选择:从人工试错到智能闭环的进化之路
  • WIN11控制面板中丢失BitLocker,找回WIN10控制面板中的BitLocker驱动器加密设置
  • TDengine 时间函数 TODAY() 用户手册
  • 架构性能优化三板斧:从10秒响应到毫秒级的演进之路
  • LeetCode_位运算
  • 每日一算:颜色分类
  • 使用自定义固定公网URL地址远程访问公司内网OA办公系统,本地无需公网IP和专线让外网访问
  • pthread_join函数
  • 视觉项目,怎么选主机
  • AI生成内容的版权问题解析与实操指南