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

批量更新和批量插入,内含jdbc工具类

一、批量更新

1.JDBC直接批量更新

  public void updateBBCPResult(List<Example> dataList, String obj) {Connection connection = null;PreparedStatement preparedStatement = null;try {connection = JDBCUitls.getConnection();connection.setAutoCommit(false);// 批量更新 BBCP 结果String sql = "UPDATE  ta_test SET amt = ? WHERE serial_no = ?";preparedStatement = connection.prepareStatement(sql);for (Example example : dataList) {preparedStatement.setDouble(1, Double.valueOf(example.getActualDeductionAmount()));preparedStatement.setString(2, example.getId());preparedStatement.addBatch();}preparedStatement.executeBatch();connection.commit();} catch (SQLException e) {try {if (connection != null) {connection.rollback();}} catch (SQLException e2) {log.error(e2.getMessage());}} finally {closeResource(preparedStatement);closeResource(connection);}}

2.使用工具类将查出来的List数据分批,然后再分批更新

工具类import java.util.ArrayList;
import java.util.List;public class BatchUtils {// 分片大小:根据每条数据的参数数计算(建议保守设为1000,避免超参)private static final int BATCH_SIZE = 1000;/*** 集合分片* @param list 原始大集合* @param <T> 数据类型* @return 分片后的小集合列表*/public static <T> List<List<T>> splitBatch(List<T> list) {List<List<T>> batchList = new ArrayList<>();if (list == null || list.isEmpty()) {return batchList;}int totalSize = list.size();// 计算需要分多少批int batchCount = (totalSize + BATCH_SIZE - 1) / BATCH_SIZE;for (int i = 0; i < batchCount; i++) {// 计算每批的起始和结束索引int start = i * BATCH_SIZE;int end = Math.min((i + 1) * BATCH_SIZE, totalSize);// 截取小集合并加入结果batchList.add(list.subList(start, end));}return batchList;}
}
二、批量插入

1.直接写sql,使用<foreach>标签

mapper

void insertUserTodoTask(@Param("list") List<UserTodoTask> userTodoTask);

xml

 <insert id="insertUserTodoTask">INSERT INTO user_todo_task (app_id,doto_id,creator_ehr,receiver_ehr,subject,module_name,content,url,create_at,send_hx_message) VALUES<foreach collection="list" item="task" separator=",">(#{task.app_id},#{task.doto_id},#{task.creator_ehr},#{task.receiver_ehr},#{task.subject},#{task.module_name},#{task.content},#{task.url},#{task.create_at},#{task.send_hx_message})</foreach></insert>

2.使用JDBCUtil工具类直接批量插入

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.google.common.base.CaseFormat;
import com.mingyoutech.appcase.tbs.util.exception.ExceptionUtils;
import com.mingyoutech.mybi.boot.framework.core.domain.R;
import com.mingyoutech.mybi.boot.framework.core.utils.SpringUtils;
import lombok.extern.slf4j.Slf4j;import javax.sql.DataSource;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.*;/*** 只用于大数据量的插入,例如几十万条这种,常规增删改查,用mybatis即可*/
@Slf4j
public class JDBCUitls {/*** 属性名与字段名映射规则*///小驼峰属性名映射下划线字段名public static final String LOWER_CAMEL_CASE_MODEL = "lowerCamelCase";//不转换(属性名与字段名相同时)public static final String DEFAULT_MODEL = "default";public static  DataSource dataSource = SpringUtils.getBean(DataSource.class);/*** 批量插入* 表名,插入字段,都在集合的泛型类中通过@TableName,和@TableField指定* @param dataList 数据集合*/public static R<String> batchSaveDate(List<?> dataList) {LinkedHashMap<String,String> linkedHashMap = new LinkedHashMap<>();String tableName;if (dataList.size()>0){Class<?> aClass = dataList.get(0).getClass();//取表名if(aClass.isAnnotationPresent(TableName.class)){TableName annotation = aClass.getAnnotation(TableName.class);tableName = annotation.value();Field[] declaredFields = aClass.getDeclaredFields();for (Field field : declaredFields){if (field.isAnnotationPresent(TableField.class)){String columnName = field.getAnnotation(TableField.class).value();String fieldName = field.getName();linkedHashMap.put(fieldName,columnName);}}if (linkedHashMap.size() == 0) return R.fail(aClass.getName()+"上没有任何一个属性拥有@TableField注释");}else {return R.fail("类上缺少@TableName注解,无法确定目标表");}}else {return R.fail("查询数据为空");}return batchSaveDate(dataList, tableName, linkedHashMap);}/*** 批量插入* 1.指定插入的字段并在filedColumnMap中声明类属性与表字段的映射关系* 2.只插入filedColumnMap中存在的字段** @param dataList       数据集合* @param tableName      表名* @param filedColumnMap 以及属性与字段的映射关系* @return 插入结果*/public static R<String> batchSaveDate(List<?> dataList, String tableName, LinkedHashMap<String, String> filedColumnMap) {int size = dataList.size();if (size == 0) {return R.fail("数据集合长度为0");}Object o = dataList.get(0);Class<?> aClass = o.getClass();Map<String, Field> fieldCache = new HashMap<>();for (String fieldName : filedColumnMap.keySet()) {try {Field field = aClass.getDeclaredField(fieldName);field.setAccessible(true);fieldCache.put(fieldName, field);} catch (NoSuchFieldException e) {return R.fail("找不到字段: " + fieldName);}}Connection conn = null;PreparedStatement ps = null;try {long startTime = System.currentTimeMillis();log.info(size + "条,开始导入到数据库时间:" + startTime + "ms");conn = dataSource.getConnection();//控制事务:默认不提交conn.setAutoCommit(false);StringBuilder stringBuilder = new StringBuilder("insert into " + tableName + "(");Set<Map.Entry<String, String>> entries = filedColumnMap.entrySet();for (Map.Entry<String, String> entry : entries) {String column = entry.getValue();stringBuilder.append(column).append(",");}stringBuilder.deleteCharAt(stringBuilder.length() - 1);stringBuilder.append(")values(");stringBuilder.append("?,".repeat(entries.size()));stringBuilder.deleteCharAt(stringBuilder.length() - 1);stringBuilder.append(")");String sql = stringBuilder.toString();ps = conn.prepareStatement(sql);//循环结果集for (Object item : dataList) {int j = 1;for (Map.Entry<String, String> entry : entries) {Field field = fieldCache.get(entry.getKey());Object filedObj =  field.get(item);String value = filedObj != null ? filedObj.toString():"";ps.setString(j, value);j++;}ps.addBatch();}//执行批处理ps.executeBatch();//手动提交事务conn.commit();long endTime = System.currentTimeMillis();log.info(size + "条,结束导入到数据库时间:" + endTime + "ms");log.info(size + "条,导入用时:" + (endTime - startTime) + "ms");} catch (Exception e) {try {if (conn!=null){conn.rollback();}} catch (SQLException throwables) {throwables.printStackTrace();}e.printStackTrace();return R.fail(ExceptionUtils.getMsg(e, 500));} finally {//关连接try {assert ps != null;ps.close();Objects.requireNonNull(conn).setAutoCommit(true);conn.close();} catch (SQLException e) {e.printStackTrace();}}return R.ok(size + "导入成功");}/*** 批量插入* 1.批量插入所有属性对应的字段** @param dataList  数据集合* @param tableName 表名* @param model     属性名与字段名映射模式*                  default :字段名与属性名一致不需要转换*                  lowerCamelCase : 小驼峰属性名映射下划线字段名* @return 插入结果*/public static R<String> batchSaveDate(List<Object> dataList, String tableName, String model) throws SQLException {int size = dataList.size();if (size == 0) {return R.fail("数据集合长度为0");}Object o = dataList.get(0);Class<?> aClass = o.getClass();//JDBC分批插入+事务操作完成对数据的插入Connection conn = null;PreparedStatement ps = null;try {long startTime = System.currentTimeMillis();log.info(size + "条,开始导入到数据库时间:" + startTime + "ms");conn = dataSource.getConnection();//控制事务:默认不提交conn.setAutoCommit(false);Field[] fields = aClass.getDeclaredFields();ArrayList<String> columns = new ArrayList<>();for (Field field : fields) {columns.add(field.getName());}String sql = getSql(columns, tableName, model);ps = conn.prepareStatement(sql);//循环结果集for (Object item : dataList) {int j = 1;for (Field field : fields) {field.setAccessible(true);String value = (String) field.get(item);ps.setString(j, value);j++;}ps.addBatch();}//执行批处理ps.executeBatch();//手动提交事务conn.commit();long endTime = System.currentTimeMillis();log.info(size + "条,结束导入到数据库时间:" + endTime + "ms");log.info(size + "条,导入用时:" + (endTime - startTime) + "ms");} catch (Exception e) {e.printStackTrace();return R.fail(ExceptionUtils.getMsg(e, 500));} finally {//关连接try {assert ps != null;ps.close();Objects.requireNonNull(conn).setAutoCommit(true);conn.close();} catch (SQLException e) {e.printStackTrace();}}return R.ok(size + "条导入成功");}/*** 批量插入,指定插入字段** @param fieldNames 需要插入到数据库的属性名称数组* @param dataList   数据集合* @param tableName  表名* @param model      属性名与字段名映射模式*                   default :字段名与属性名一致*                   lowerCamelCase : 小驼峰转换下划线* @return 插入结果*/public static R<String> batchSaveDate(List<Object> dataList, String tableName, String[] fieldNames, String model) {int size = dataList.size();if (size == 0) {return R.fail("数据集合长度为0");}Object o = dataList.get(0);Class<?> aClass = o.getClass();//JDBC分批插入+事务操作完成对数据的插入Connection conn = null;PreparedStatement ps = null;try {long startTime = System.currentTimeMillis();log.info(size + "条,开始导入到数据库时间:" + startTime + "ms");conn = dataSource.getConnection();//控制事务:默认不提交conn.setAutoCommit(false);String sql = getSql(Arrays.asList(fieldNames), tableName, model);ps = conn.prepareStatement(sql);//循环结果集for (Object item : dataList) {int j = 1;for (String fieldName : fieldNames) {Field field = aClass.getDeclaredField(fieldName);field.setAccessible(true);String value = (String) field.get(item);ps.setString(j, value);j++;}ps.addBatch();}//执行批处理ps.executeBatch();//手动提交事务conn.commit();long endTime = System.currentTimeMillis();log.info(size + "条,结束导入到数据库时间:" + endTime + "ms");log.info(size + "条,导入用时:" + (endTime - startTime) + "ms");} catch (Exception e) {e.printStackTrace();return R.fail(ExceptionUtils.getMsg(e, 500));} finally {//关连接try {assert ps != null;ps.close();Objects.requireNonNull(conn).setAutoCommit(true);conn.close();} catch (SQLException e) {e.printStackTrace();}}return R.ok(size + "条导入成功");}/*** 生成插入sql* @param filedNames 要插入的属性名数组* @param tableName  表名* @param model      属性名与字段的自动映射模式* @return 插入sql*/private static String getSql(List<String> filedNames, String tableName, String model) {StringBuilder stringBuilder = new StringBuilder("insert into " + tableName + " (");if (model.equals(LOWER_CAMEL_CASE_MODEL)) {for (String column : filedNames) {column = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, column);stringBuilder.append(column).append(",");}} else if (model.equals(DEFAULT_MODEL)) {for (String column : filedNames) {stringBuilder.append(column).append(",");}}stringBuilder.deleteCharAt(stringBuilder.length() - 1);stringBuilder.append(")values(");stringBuilder.append("?,".repeat(filedNames.size()));stringBuilder.deleteCharAt(stringBuilder.length() - 1);stringBuilder.append(")");return stringBuilder.toString();}public static Connection getConnection() throws SQLException {return dataSource.getConnection();}}

文章转载自:

http://LmyJSOeh.bsbcp.cn
http://BnJruwfQ.bsbcp.cn
http://v6fIh5uA.bsbcp.cn
http://rfIYMFHZ.bsbcp.cn
http://9qOye1CF.bsbcp.cn
http://OR6TfPep.bsbcp.cn
http://KK4DcCj0.bsbcp.cn
http://C89k4Ycu.bsbcp.cn
http://BBrercwM.bsbcp.cn
http://Vg7shhAv.bsbcp.cn
http://nJBHhPxj.bsbcp.cn
http://CbCTGpzd.bsbcp.cn
http://FazkZYBG.bsbcp.cn
http://JI1kHqT7.bsbcp.cn
http://mTsHJZTn.bsbcp.cn
http://sEXbCjaZ.bsbcp.cn
http://XOGVdFiu.bsbcp.cn
http://tR2Y2iQD.bsbcp.cn
http://SHV58cVm.bsbcp.cn
http://CBHBhPjz.bsbcp.cn
http://3L28O3QQ.bsbcp.cn
http://9bPIUTcC.bsbcp.cn
http://CP4NWVTJ.bsbcp.cn
http://YxKoAbCj.bsbcp.cn
http://snMphbSo.bsbcp.cn
http://nbgNB2Pl.bsbcp.cn
http://kWiuHN86.bsbcp.cn
http://KMEezCs0.bsbcp.cn
http://3820m5GZ.bsbcp.cn
http://87Wtisji.bsbcp.cn
http://www.dtcms.com/a/385026.html

相关文章:

  • 3D地球可视化教程 - 第2篇:夜晚纹理与着色器入门
  • Ajax笔记2
  • DDoS高防IP是什么? DDoS攻击会暴露IP吗?
  • Java 设计模式——原则:从理论约束到项目落地指南
  • 从零开始打造个性化浏览器导航扩展:极简高级风格设计
  • 软件包安装
  • QARM:Quantitative Alignment Multi-Modal Recommendation at Kuaishou
  • 通达信抓波段指标(主图)
  • Django基础环境入门
  • Java学习笔记2——简单语法
  • LLM-LLM大语言模型快速认识
  • Winogender:衡量NLP模型性别偏见的基准数据集
  • Oracle UNDO表空间使用率过高解决方案
  • Qt 中 OPC UA 通讯实战
  • 生产制造数智化
  • ensp配置学习笔记 比赛版 vlan 静态路由 ospf bgp dhcp
  • java-代码随想录第33天|62.不同路径、63.不同路径II
  • 突破限制:FileCodeBox远程文件分享新体验
  • 对讲机模块 TDD 噪音:原理、快速止噪解决方案
  • 知识点11:总线驱动的多Agent调度
  • 使用 Docker 搭建私有 PyPI 镜像仓库:支持多平台二进制包同步
  • HarmonyOS实现快递APP自动识别地址(国际版)
  • IPsec实验笔记
  • 工业IOT平台助力水泥集团实现数字化转型
  • 【CSS】图片自适应等比例缩放
  • Java 21 虚拟线程高并发落地全指南:中间件适配、场景匹配与细节优化的技术实践
  • 设计模式(C++)详解—适配器模式(1)
  • 圆周点生成的数学原理与Python实现
  • 牛客:校门外的树
  • JavaScript数据网格方案AG Grid 34.2 发布:更灵活的数据结构、更流畅的大数据交互与全新 UI 体验