批量更新操作

批量更新逻辑:

底层真正的批量更新(一次请求发送批量更新语句)

底层循环发送语句(假批量更新)—本质上就是一条一条更新

批量更新逻辑判断

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 关于批量更新操作的实现相关推荐

  1. java mongodb批量更新数据_MongoDB的批量查询条件进行批量更新数据

    今天遇到这样一个场景:在Java中批量更新MongoDB数据,不过每次更新的条件有不一样,那如何有效地进行更新操作呢? 刚开始的时候,我是想到循环批量更新操作,即每一种查询条件进行一次批量更新过程,这 ...

  2. mybatis批量插入(insert)和批量更新(update)

    文章目录 一.Mybatis批量插入 二.批量更新 前言:这两天在做mybatis批量插入和更新的时候,对这块不是很清楚,所以今天写篇文章,巩固加深印象. 一.Mybatis批量插入 批量插入的sql ...

  3. SqlBulkCopy与触发器,批量插入表(存在则更新,不存在则插入)

    原文:SqlBulkCopy与触发器,批量插入表(存在则更新,不存在则插入) 临时表:Test /****** 对象: Table [dbo].[Test] 脚本日期: 05/10/2013 11:4 ...

  4. oracle批量查询更新,Oracle批量查询、删除、更新使用BULK COLLECT提高效率

    BULK COLLECT(成批聚合类型)和数组集合type类型is table of 表%rowtype index by binary_integer用法笔记. 例1: 批量查询项目资金账户号为 & ...

  5. batchupdate写法_mybatis执行批量插入insert和批量更新update

    Mybatis批量插入和批量更新数据的资料相信大家从网上能查找到很多资料,本文重点总结一下mybatis执行批量插入insert和批量更新update数据.在mysql数据库中批量插入,如:inser ...

  6. mysql循环更新数据_大批量更新数据mysql批量更新的四种方法

    mysql 批量更新如果一条条去更新效率是相当的慢, 循环一条一条的更新记录,一条记录update一次,这样性能很差,也很容易造成阻塞. mysql 批量更新共有以下四种办法 1..replace i ...

  7. 大批量更新数据mysql批量更新的四种方法

    转载一篇大批量更新mysql数据的办法,为了便于阅读根据原文做了缩减. mysql 批量更新如果一条条去更新效率是相当的慢, 循环一条一条的更新记录,一条记录update一次,这样性能很差,也很容易造 ...

  8. mysql 批量replace into_replace into 批量更新

    1..replace into 批量更新 $sql = replace into test_tbl (id,dr) values (1,'2'),(2,'3'),...(x,'y'); test_tb ...

  9. 微信windows版_刚刚微信内测更新!可以批量管理好友,太方便了

    微信清理好友一直是一个世纪难题,不知道大家有没有跟小雷一样的烦恼,每次清理好友都要一个个点,着实太麻烦,特别是像小雷我这种"交际王",微信四五千好友,每次清理都要花大半天的时间.想 ...

最新文章

  1. C语言单链表求环,并返回环的起始节点
  2. 我的AngularJS学习轨迹
  3. python股票数据预处理_Python股票处理之六_数据预处理A
  4. x264_macroblock_cache_load()
  5. java单个数组求积_[剑指offer][Java]构建乘积数组
  6. (转)RabbitMQ学习之Headers交换类型(java)
  7. arm汇编指令集_汇编入门第一篇,小白也能看懂
  8. vsco怎么两个滤镜叠加_做图比设计师还快?!这帮饭圈女孩是怎么做到的?
  9. 关于STM8S003f3p6的定时器2通道3无法输出pwm的问题
  10. 开发者API资源(接口整理)
  11. 单例模式中的懒汉模式和饿汉模式
  12. iPhone如何连接U盘呢 iphone连接u盘方法教程
  13. WeChat-JSAPI支付
  14. 腾讯笔试题——逆序对
  15. 常见动词的过去式和过去分词
  16. 计算某年某月某日是星期几(基姆拉尔森计算公式)
  17. 深入理解Flash的沙箱
  18. 百度API---详解
  19. Zedboard(一)开发环境Vivado
  20. yolo和以往算法的区别/yolo为什么叫yolo

热门文章

  1. ultraiso软碟通 无法保存hfs文件卷
  2. 设计模式(第十式:桥梁模式)
  3. mysql 聚合函数求平均数_MySQL教程63-MySQL 聚合函数
  4. React加购物车抛物线动画的实现
  5. c语言中存贮班级学生的变量,C语言----变量教案.docx
  6. C 语言实现斐波那契数列,解决递归实现缺陷(算法)
  7. QBC (Query By Criteria)
  8. 【Python】中文编解码操作
  9. 五月,我们骑车去香格里拉
  10. SQL Server Connectors By Thread Pool | DTSQLServerTP 插件使用说明