JAVA怎么批量更新mysql_java 关于批量更新操作的实现
批量更新操作
批量更新逻辑:
底层真正的批量更新(一次请求发送批量更新语句)
底层循环发送语句(假批量更新)—本质上就是一条一条更新
批量更新逻辑判断
JdbcTemplate
JdbcUtils.supportsBatchUpdates(ps.getConnection())—判断连接是否支持批量更新
publicint[] batchUpdate(Stringsql,finalBatchPreparedStatementSetterpss)throwsDataAccessException {
if(logger.isDebugEnabled()) {
logger.debug("Executing SQL batch update ["+sql+"]");
}
returnexecute(sql,newPreparedStatementCallback() {
publicint[] doInPreparedStatement(PreparedStatementps)throwsSQLException {
try{
intbatchSize=pss.getBatchSize();
InterruptibleBatchPreparedStatementSetteripss=
(pssinstanceofInterruptibleBatchPreparedStatementSetter ?
(InterruptibleBatchPreparedStatementSetter)pss:null);
if(JdbcUtils.supportsBatchUpdates(ps.getConnection())) {
for(inti= 0;i
pss.setValues(ps,i);
if(ipss!=null&&ipss.isBatchExhausted(i)) {
break;
}
ps.addBatch();
}
returnps.executeBatch();
}
else{
ListrowsAffected=newArrayList();
for(inti= 0;i
pss.setValues(ps,i);
if(ipss!=null&&ipss.isBatchExhausted(i)) {
break;
}
rowsAffected.add(ps.executeUpdate());
}
int[]rowsAffectedArray=newint[rowsAffected.size()];
for(inti= 0;i
rowsAffectedArray[i] =rowsAffected.get(i);
}
returnrowsAffectedArray;
}
}
finally{
if(pssinstanceofParameterDisposer) {
((ParameterDisposer)pss).cleanupParameters();
}
}
}
});
}
备注:
Mysql: DatabaseMetaData 直接返回true
publicbooleansupportsBatchUpdates()throwsSQLException {
returntrue;
}
Mysql最终走的原生jdbc Statement----所以
即便JdbcUtils.supportsBatchUpdates(ps.getConnection())为true了也不一定是真正的批处理
Oracle: OracleDatabaseMetaData 直接返回true
oracle最终走的原生jdbc Statement----所以
即便JdbcUtils.supportsBatchUpdates(ps.getConnection())为true了也不一定是真正的批处理
SqlSessionTemplate
第一步:配置一个SqlSessionTemplate, Batch模式
第二步:代码开启事务,必须要开启,只有开启同一个事务,循环insert底层才会只执行addBatch并且不执行executeBatch,最后统一
public void test(){
SqlSessionTemplate template=ApplicationContextUtils.getBean("batchSqlSession",SqlSessionTemplate.class);
for (int i = 0; i < 20000; i++) {
Map m=new HashMap();
m.put("id",i);
m.put("name","test"+i);
m.put("age", 1+i);
template.insert("inpspect.testBatch",m);
}
List list=template.flushStatements();
}
原生jdbc Statement
Mysql
PreparedStatement形式
com.mysql.jdbc .PreparedStatement类:
批量新增的条件:rewriteBatchedStatements为true就可以了
批量修改或者删除:rewriteBatchedStatements为true,并且批量的语句>3条
批量修改或者删除的数量>3(this.batchedArgs.size() > 3)
Statement形式
com.mysql.jdbc. StatementImpl.executeBatch
allowMultiQueries为true或者rewriteBatchedStatements为true并且批量语句大于4条
Oracle
PreparedStatement形式
依赖类:oracle.jdbc.driver. T4CPreparedStatement
Statement形式
依赖oracle.jdbc.driver.T4CStatement。 不支持批量更新操作,因为本质上还是一条sql一次请求,执行完一条再执行下一条。跟mysql不一样,mysql statement模式会分号拼接
数据库配置支持批量更新
Mysql
PreparedStatement形式
设置:rewriteBatchedStatements=true
例如:jdbc:mysql://xxxx:3306/cloud_nms?rewriteBatchedStatements=true&autoReconnect=true&useUnicode=true&noAccessToProcedureBodies=true&characterEncoding=utf8&allowMultiQueries=true
Statement形式
设置:allowMultiQueries=true
Mysql批量更新返回值问题
批量更新的逻辑
PreparedStatement形式
PreparedStatement st=conn.prepareStatement(" insert into test_batch(id,name,age) values(?,?,?)");
for (int i = 20000; i < 20003; i++) {
Map m=new HashMap();
m.put("id",i);
m.put("name","test"+i);
m.put("age", 1+i);
st.setInt(1, i);
st.setString(2, "test"+i);
st.setInt(3, 1+i);
st.addBatch();
}
int[] aa=st.executeBatch();
新增:多个值拼成一条sql语句,多个值逗号分隔
最终拼接成sql: insert into xxx values(1,1,1),(2,2,2),(3,3,3),…..
修改:最终多个语句分号分隔,一次执行
最终拼接成:update xxx set a=xxxx where id=1; update xxx set a=xxxx where id=2; update xxx set a=xxxx where id=3
删除:最终多个语句分号分隔,一次执行
最终拼接成:delete from xxx where id=1; delete from xxx where id=2; delete from xxx where id=3
Statement
新增、修改、删除最终都是以多个语句分号分隔,一次执行
insert into xxx values(1,1,1); insert into xxx values (2,2,2); insert into xxx values (3,3,3);…
oracle
PreparedStatement形式
无需设置,依赖的是oracle的动态sql,绑定参数
Statement形式
不支持,无论怎么设置都不支持
oracle批量更新返回值问题
批量更新的逻辑
PreparedStatement形式
Statement
还是单条执行sql
批量更新的返回值
PreparedStatement形式
String sql="delete test_batch where id=?";
PreparedStatement st= conn.prepareStatement(sql);
for (int i =0; i < 4; i++) {
st.setString(1, "idi"+i+"d");
st.addBatch();
}
Int[] result=st.executeBatch();--返回[-2,-2,-2,-2]
都返回-2
新增、删除、更新返回:[-2,-2,-2] 新增批量执行其实是封装成了一条语句,而这一条语句影响了多行,mysql底层为了返回标准化,就将每条对应更新的结果值人为的赋值-2。-2表示执行成功了
Statement形式
新增、修改、删除都会返回:[0,1,1]---0表示影响了0行,1表示影响了一行.
常见批量更新问题
Mysql环境,使用jdbctempate.batchUpdate方法,或者使用了 原生jdbc的executeBatch方法批量更新的时候,有的语句能成功有的不能成功,但是成功的语句会入库。
原因:没有设置rewriteBatchedStatements=true,导致最终mysql底层还是一条一条的更新,由于没有关闭自动提交,所以执行一条就提交一条。当其中一条报错的时候肯定就不会入库了,对应的该语句的执行结果是-3,然后继续执行后面的语句不会停止的。
最终的结果会是:异常语句失败忽略,正常语句执行成功入库
见下图: com.mysql.jdbc. PreparedStatement. executeBatchSerially方法
问题延伸
如果想要批量执行的语句要么成功要么失败解决办法:
通过设置rewriteBatchedStatements=true,让mysql驱动底层就一次把批量sql发送过去执行,这样只要有一条有问题,那么就都不会执行入库
通过事务控制,如果不设置rewriteBatchedStatements=true,底层是一条一条的发的,那么可以通过手动提交,执行完以后没异常再提交,有异常回滚。最好同时设置continueBatchOnError=false,这样的话,有异常不继续,性能更高
JAVA怎么批量更新mysql_java 关于批量更新操作的实现相关推荐
- java mongodb批量更新数据_MongoDB的批量查询条件进行批量更新数据
今天遇到这样一个场景:在Java中批量更新MongoDB数据,不过每次更新的条件有不一样,那如何有效地进行更新操作呢? 刚开始的时候,我是想到循环批量更新操作,即每一种查询条件进行一次批量更新过程,这 ...
- mybatis批量插入(insert)和批量更新(update)
文章目录 一.Mybatis批量插入 二.批量更新 前言:这两天在做mybatis批量插入和更新的时候,对这块不是很清楚,所以今天写篇文章,巩固加深印象. 一.Mybatis批量插入 批量插入的sql ...
- SqlBulkCopy与触发器,批量插入表(存在则更新,不存在则插入)
原文:SqlBulkCopy与触发器,批量插入表(存在则更新,不存在则插入) 临时表:Test /****** 对象: Table [dbo].[Test] 脚本日期: 05/10/2013 11:4 ...
- oracle批量查询更新,Oracle批量查询、删除、更新使用BULK COLLECT提高效率
BULK COLLECT(成批聚合类型)和数组集合type类型is table of 表%rowtype index by binary_integer用法笔记. 例1: 批量查询项目资金账户号为 & ...
- batchupdate写法_mybatis执行批量插入insert和批量更新update
Mybatis批量插入和批量更新数据的资料相信大家从网上能查找到很多资料,本文重点总结一下mybatis执行批量插入insert和批量更新update数据.在mysql数据库中批量插入,如:inser ...
- mysql循环更新数据_大批量更新数据mysql批量更新的四种方法
mysql 批量更新如果一条条去更新效率是相当的慢, 循环一条一条的更新记录,一条记录update一次,这样性能很差,也很容易造成阻塞. mysql 批量更新共有以下四种办法 1..replace i ...
- 大批量更新数据mysql批量更新的四种方法
转载一篇大批量更新mysql数据的办法,为了便于阅读根据原文做了缩减. mysql 批量更新如果一条条去更新效率是相当的慢, 循环一条一条的更新记录,一条记录update一次,这样性能很差,也很容易造 ...
- mysql 批量replace into_replace into 批量更新
1..replace into 批量更新 $sql = replace into test_tbl (id,dr) values (1,'2'),(2,'3'),...(x,'y'); test_tb ...
- 微信windows版_刚刚微信内测更新!可以批量管理好友,太方便了
微信清理好友一直是一个世纪难题,不知道大家有没有跟小雷一样的烦恼,每次清理好友都要一个个点,着实太麻烦,特别是像小雷我这种"交际王",微信四五千好友,每次清理都要花大半天的时间.想 ...
最新文章
- C语言单链表求环,并返回环的起始节点
- 我的AngularJS学习轨迹
- python股票数据预处理_Python股票处理之六_数据预处理A
- x264_macroblock_cache_load()
- java单个数组求积_[剑指offer][Java]构建乘积数组
- (转)RabbitMQ学习之Headers交换类型(java)
- arm汇编指令集_汇编入门第一篇,小白也能看懂
- vsco怎么两个滤镜叠加_做图比设计师还快?!这帮饭圈女孩是怎么做到的?
- 关于STM8S003f3p6的定时器2通道3无法输出pwm的问题
- 开发者API资源(接口整理)
- 单例模式中的懒汉模式和饿汉模式
- iPhone如何连接U盘呢 iphone连接u盘方法教程
- WeChat-JSAPI支付
- 腾讯笔试题——逆序对
- 常见动词的过去式和过去分词
- 计算某年某月某日是星期几(基姆拉尔森计算公式)
- 深入理解Flash的沙箱
- 百度API---详解
- Zedboard(一)开发环境Vivado
- yolo和以往算法的区别/yolo为什么叫yolo
热门文章
- ultraiso软碟通 无法保存hfs文件卷
- 设计模式(第十式:桥梁模式)
- mysql 聚合函数求平均数_MySQL教程63-MySQL 聚合函数
- React加购物车抛物线动画的实现
- c语言中存贮班级学生的变量,C语言----变量教案.docx
- C 语言实现斐波那契数列,解决递归实现缺陷(算法)
- QBC (Query By Criteria)
- 【Python】中文编解码操作
- 五月,我们骑车去香格里拉
- SQL Server Connectors By Thread Pool | DTSQLServerTP 插件使用说明