Spring JdbcTemplate.batchUpdate()
Posted allway2
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring JdbcTemplate.batchUpdate()相关的知识,希望对你有一定的参考价值。
在此页面上,我们将学习使用Spring JdbcTemplate.batchUpdate()方法。batchUpdate()方法使用批处理发出多个 SQL。batchUpdate()接受参数如下。
1.
int[] batchUpdate(String... sql) throws DataAccessException
使用批处理在单个 JDBC 语句上发出多个 SQL 更新。如果 JDBC 驱动程序不支持批处理更新,则该方法将回退到单个语句上的单独更新。
2.
int[] batchUpdate(String sql, BatchPreparedStatementSetter pss) throws DataAccessException
使用批量更新和BatchPreparedStatementSetter
设置值在单个PreparedStatement上发出多个更新语句。如果 JDBC 驱动程序不支持批量更新,该方法将回退到单个PreparedStatement上的单独更新。
3.
<T> int[][] batchUpdate(String sql, Collection<T> batchArgs, int batchSize, ParameterizedPreparedStatementSetter<T> pss) throws DataAccessException
使用提供的 SQL 语句和提供的参数集合执行多个批处理。每批应具有“批次大小”中标明的大小。
4.
int[] batchUpdate(String sql, List<Object[]> batchArgs) throws DataAccessException
使用提供的 SQL 语句和提供的参数批处理执行批处理。
5.
int[] batchUpdate(String sql, List<Object[]> batchArgs, int[] argTypes) throws DataAccessException
使用提供的 SQL 语句和提供的参数批处理执行批处理。
参数:
sql定义批处理操作中使用的 SQL 查询。
pss是设置参数的对象。
batchArgs是包含查询参数批处理的对象数组列表。batchSize
是批量大小。
返回:
该方法返回受每个语句影响的行数的数组。
抛出:
如果发布更新时出现任何问题,该方法将抛出DataAccessException。
使用Spring Boot的示例
PersonDAO.java
package com.concretepage;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.ParameterizedPreparedStatementSetter;
import org.springframework.stereotype.Repository;
@Repository
public class PersonDAO
@Autowired
private JdbcTemplate jdbcTemplate;
// batchUpdate(String... sql)
public void addPersonsUsingBatch1(List<Person> list)
String sql1 = "insert into person (name, age) values ('" + list.get(0).getName() + "', " + list.get(0).getAge() + ")";
String sql2 = "insert into person (name, age) values ('" + list.get(1).getName() + "', " + list.get(1).getAge() + ")";
int[] insertedRows = jdbcTemplate.batchUpdate(sql1, sql2);
// batchUpdate(String sql, BatchPreparedStatementSetter pss)
public void addPersonsUsingBatch2(List<Person> list)
String sql = "insert into person (name, age) values (?, ?)";
int[] insertedRows = jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter()
@Override
public void setValues(PreparedStatement ps, int i) throws SQLException
ps.setString(1, list.get(i).getName());
ps.setInt(2, list.get(i).getAge());
@Override
public int getBatchSize()
return list.size();
);
// batchUpdate(String sql, Collection<T> batchArgs, int batchSize, ParameterizedPreparedStatementSetter<T> pss)
public void addPersonsUsingBatch3(List<Person> list)
String sql = "insert into person (name, age) values (?, ?)";
int[][] insertedRows = jdbcTemplate.batchUpdate(sql, list, 2,
new ParameterizedPreparedStatementSetter<Person>()
@Override
public void setValues(PreparedStatement ps, Person p) throws SQLException
ps.setString(1, p.getName());
ps.setInt(2, p.getAge());
);
// batchUpdate(String sql, List<Object[]> batchArgs)
public void addPersonsUsingBatch4(List<Person> list)
String sql = "insert into person (name, age) values (?, ?)";
Object[] ob1 = list.get(0).getName(), list.get(0).getAge();
Object[] ob2 = list.get(1).getName(), list.get(1).getAge();
int[] insertedRows = jdbcTemplate.batchUpdate(sql, Arrays.asList(ob1, ob2));
// batchUpdate(String sql, List<Object[]> batchArgs, int[] argTypes)
public void addPersonsUsingBatch5(List<Person> list)
String sql = "insert into person (name, age) values (?, ?)";
Object[] ob1 = list.get(0).getName(), list.get(0).getAge();
Object[] ob2 = list.get(1).getName(), list.get(1).getAge();
int[] argTypes = java.sql.Types.CHAR, java.sql.Types.INTEGER;
int[] insertedRows = jdbcTemplate.batchUpdate(sql, Arrays.asList(ob1, ob2), argTypes);
Person.java
package com.concretepage;
public class Person
private int id;
private String name;
private int age;
public Person(String name, int age)
this.name = name;
this.age = age;
public int getId()
return id;
public void setId(int id)
this.id = id;
public String getName()
return name;
public int getAge()
return age;
@Override
public String toString()
return id + " - " + name + " - " + age;
application.properties
spring.datasource.url=jdbc:mysql://localhost:3306/concretepage?autoReconnect=true&useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
MySQL 表:person
CREATE TABLE `person` (
`id` INT(5) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(100) NOT NULL,
`age` INT(3) NOT NULL,
PRIMARY KEY (`id`)
)
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.concretepage</groupId>
<artifactId>soap-ws</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>spring-demo</name>
<description>Spring Demo Application</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.4</version>
<relativePath />
</parent>
<properties>
<java.version>16</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.30</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
MyApplication.java
package com.concretepage;
import java.util.Arrays;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
@SpringBootApplication
public class MyApplication
public static void main(String[] args)
ApplicationContext ctx = SpringApplication.run(MyApplication.class, args);
PersonDAO personDAO = ctx.getBean(PersonDAO.class);
personDAO.addPersonsUsingBatch1(Arrays.asList(new Person("Mohan 1", 21), new Person("Shiva 1", 31)));
personDAO.addPersonsUsingBatch1(Arrays.asList(new Person("Mohan 2", 22), new Person("Shiva 2", 32)));
personDAO.addPersonsUsingBatch1(Arrays.asList(new Person("Mohan 3", 23), new Person("Shiva 3", 33)));
personDAO.addPersonsUsingBatch1(Arrays.asList(new Person("Mohan 4", 24), new Person("Shiva 4", 34)));
personDAO.addPersonsUsingBatch1(Arrays.asList(new Person("Mohan 5", 25), new Person("Shiva 5", 35)));
以下行将插入到数据库中。
参考
下载源代码
spring-jdbctemplate-batchupdate.zip
Spring框架系列 - Spring和Spring框架组成
Spring是什么?它是怎么诞生的?有哪些主要的组件和核心功能呢? 本文通过这几个问题帮助你构筑Spring和Spring Framework的整体认知。@pdai
- Core Container(Spring的核心容器)
- Data Access/Integration(数据访问/集成)
- Web模块
- AOP、Aspects、Instrumentation和Messaging
- Test模块
- 更多文章
什么是Spring?
首先,Spring是什么?它是怎么诞生的?它的诞生是为了解决什么问题?@pdai
Spring的起源
百度百科中关于Spring的起源介绍如下:
要谈Spring的历史,就要先谈J2EE。J2EE应用程序的广泛实现是在1999年和2000年开始的,它的出现带来了诸如事务管理之类的核心中间层概念的标准化,但是在实践中并没有获得绝对的成功,因为开发效率,开发难度和实际的性能都令人失望。
曾经使用过EJB开发JAVA EE应用的人,一定知道,在EJB开始的学习和应用非常的艰苦,很多东西都不能一下子就很容易的理解。EJB要严格地实现各种不同类型的接口,类似的或者重复的代码大量存在。而配置也是复杂和单调,同样使用JNDI进行对象查找的代码也是单调而枯燥。虽然有一些开发工作随着xdoclet的出现,而有所缓解,但是学习EJB的高昂代价,和极低的开发效率,极高的资源消耗,都造成了EJB的使用困难。而Spring出现的初衷就是为了解决类似的这些问题。
Spring的一个最大的目的就是使JAVA EE开发更加容易。同时,Spring之所以与Struts、Hibernate等单层框架不同,是因为Spring致力于提供一个以统一的、高效的方式构造整个应用,并且可以将单层框架以最佳的组合揉和在一起建立一个连贯的体系。可以说Spring是一个提供了更完善开发环境的一个框架,可以为POJO(Plain Ordinary Java Object)对象提供企业级的服务。
Spring的形成,最初来自Rod Jahnson所著的一本很有影响力的书籍《Expert One-on-One J2EE Design and Development》,就是在这本书中第一次出现了Spring的一些核心思想,该书出版于2002年。
Spring的特性和优势
Spring Framework有哪些特性,用了这个框架对开发而言有什么好处呢?
从Spring 框架的特性来看:
- 非侵入式:基于Spring开发的应用中的对象可以不依赖于Spring的API
- 控制反转:IOC——Inversion of Control,指的是将对象的创建权交给 Spring 去创建。使用 Spring 之前,对象的创建都是由我们自己在代码中new创建。而使用 Spring 之后。对象的创建都是给了 Spring 框架。
- 依赖注入:DI——Dependency Injection,是指依赖的对象不需要手动调用 setXX 方法去设置,而是通过配置赋值。
- 面向切面编程:Aspect Oriented Programming——AOP
- 容器:Spring 是一个容器,因为它包含并且管理应用对象的生命周期
- 组件化:Spring 实现了使用简单的组件配置组合成一个复杂的应用。在 Spring 中可以使用XML和Java注解组合这些对象。
- 一站式:在 IOC 和 AOP 的基础上可以整合各种企业应用的开源框架和优秀的第三方类库(实际上 Spring 自身也提供了表现层的 SpringMVC 和持久层的 Spring JDBC)
从使用Spring 框架的好处看:
- Spring 可以使开发人员使用 POJOs 开发企业级的应用程序。只使用 POJOs 的好处是你不需要一个 EJB 容器产品,比如一个应用程序服务器,但是你可以选择使用一个健壮的 servlet 容器,比如 Tomcat 或者一些商业产品。
- Spring 在一个单元模式中是有组织的。即使包和类的数量非常大,你只要担心你需要的,而其它的就可以忽略了。
- Spring 不会让你白费力气做重复工作,它真正的利用了一些现有的技术,像 ORM 框架、日志框架、JEE、Quartz 和 JDK 计时器,其他视图技术。
- 测试一个用 Spring 编写的应用程序很容易,因为环境相关的代码被移动到这个框架中。此外,通过使用 JavaBean-style POJOs,它在使用依赖注入注入测试数据时变得更容易。
- Spring 的 web 框架是一个设计良好的 web MVC 框架,它为比如 Structs 或者其他工程上的或者不怎么受欢迎的 web 框架提供了一个很好的供替代的选择。MVC 模式导致应用程序的不同方面(输入逻辑,业务逻辑和UI逻辑)分离,同时提供这些元素之间的松散耦合。模型(Model)封装了应用程序数据,通常它们将由 POJO 类组成。视图(View)负责渲染模型数据,一般来说它生成客户端浏览器可以解释 HTML 输出。控制器(Controller)负责处理用户请求并构建适当的模型,并将其传递给视图进行渲染。
- Spring 对 JavaEE 开发中非常难用的一些 API(JDBC、JavaMail、远程调用等),都提供了封装,使这些API应用难度大大降低。
- 轻量级的 IOC 容器往往是轻量级的,例如,特别是当与 EJB 容器相比的时候。这有利于在内存和 CPU 资源有限的计算机上开发和部署应用程序。
- Spring 提供了一致的事务管理接口,可向下扩展到(使用一个单一的数据库,例如)本地事务并扩展到全局事务(例如,使用 JTA)
Spring有哪些组件?
Spring Framework有哪些组件呢?
下图来自,官方文档 Spring-framework 5.0;需要注意的是,虽然这个图来源于Spring Framwork5.0 M4 版本,但是它依然是V4版本的图,比如Spring 5版本中的web模块已经去掉了Portlet模块,新增了WebFlux模块等。
上图中包含了 Spring 框架的所有模块,这些模块可以满足一切企业级应用开发的需求,在开发过程中可以根据需求有选择性地使用所需要的模块。下面分别对这些模块的作用进行简单介绍(并且结合SpringFramework5.x源码模块帮助你对应好各模块关系)。
Core Container(Spring的核心容器)
Spring 的核心容器是其他模块建立的基础,由 Beans 模块、Core 核心模块、Context 上下文模块和 SpEL 表达式语言模块组成,没有这些核心容器,也不可能有 AOP、Web 等上层的功能。具体介绍如下。
- Beans 模块:提供了框架的基础部分,包括控制反转和依赖注入。
- Core 核心模块:封装了 Spring 框架的底层部分,包括资源访问、类型转换及一些常用工具类。
- Context 上下文模块:建立在 Core 和 Beans 模块的基础之上,集成 Beans 模块功能并添加资源绑定、数据验证、国际化、Java EE 支持、容器生命周期、事件传播等。ApplicationContext 接口是上下文模块的焦点。
- SpEL 模块:提供了强大的表达式语言支持,支持访问和修改属性值,方法调用,支持访问及修改数组、容器和索引器,命名变量,支持算数和逻辑运算,支持从 Spring 容器获取 Bean,它也支持列表投影、选择和一般的列表聚合等。
对应的源码模块如下:
Data Access/Integration(数据访问/集成)
数据访问/集成层包括 JDBC、ORM、OXM、JMS 和 Transactions 模块,具体介绍如下。
- JDBC 模块:提供了一个 JBDC 的样例模板,使用这些模板能消除传统冗长的 JDBC 编码还有必须的事务控制,而且能享受到 Spring 管理事务的好处。
- ORM 模块:提供与流行的“对象-关系”映射框架无缝集成的 API,包括 JPA、JDO、Hibernate 和 MyBatis 等。而且还可以使用 Spring 事务管理,无需额外控制事务。
- OXM 模块:提供了一个支持 Object /XML 映射的抽象层实现,如 JAXB、Castor、XMLBeans、JiBX 和 XStream。将 Java 对象映射成 XML 数据,或者将XML 数据映射成 Java 对象。
- JMS 模块:指 Java 消息服务,提供一套 “消息生产者、消息消费者”模板用于更加简单的使用 JMS,JMS 用于用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信。
- Transactions 事务模块:支持编程和声明式事务管理。
对应的源码模块如下:
Web模块
Spring 的 Web 层包括 Web、Servlet、WebSocket 和 Webflux 组件,具体介绍如下。
- Web 模块:提供了基本的 Web 开发集成特性,例如多文件上传功能、使用的 Servlet 监听器的 IOC 容器初始化以及 Web 应用上下文。
- Servlet 模块:提供了一个 Spring MVC Web 框架实现。Spring MVC 框架提供了基于注解的请求资源注入、更简单的数据绑定、数据验证等及一套非常易用的 JSP 标签,完全无缝与 Spring 其他技术协作。
- WebSocket 模块:提供了简单的接口,用户只要实现响应的接口就可以快速的搭建 WebSocket Server,从而实现双向通讯。
- Webflux 模块: Spring WebFlux 是 Spring Framework 5.x中引入的新的响应式web框架。与Spring MVC不同,它不需要Servlet API,是完全异步且非阻塞的,并且通过Reactor项目实现了Reactive Streams规范。Spring WebFlux 用于创建基于事件循环执行模型的完全异步且非阻塞的应用程序。
此外Spring4.x中还有Portlet 模块,在Spring 5.x中已经移除
- Portlet 模块:提供了在 Portlet 环境中使用 MVC 实现,类似 Web-Servlet 模块的功能。
对应的源码模块如下:
AOP、Aspects、Instrumentation和Messaging
在 Core Container 之上是 AOP、Aspects 等模块,具体介绍如下:
- AOP 模块:提供了面向切面编程实现,提供比如日志记录、权限控制、性能统计等通用功能和业务逻辑分离的技术,并且能动态的把这些功能添加到需要的代码中,这样各司其职,降低业务逻辑和通用功能的耦合。
- Aspects 模块:提供与 AspectJ 的集成,是一个功能强大且成熟的面向切面编程(AOP)框架。
- Instrumentation 模块:提供了类工具的支持和类加载器的实现,可以在特定的应用服务器中使用。
- messaging 模块:Spring 4.0 以后新增了消息(Spring-messaging)模块,该模块提供了对消息传递体系结构和协议的支持。
- jcl 模块: Spring 5.x中新增了日志框架集成的模块。
对应的源码模块如下:
Test模块
Test 模块:Spring 支持 Junit 和 TestNG 测试框架,而且还额外提供了一些基于 Spring 的测试功能,比如在测试 Web 框架时,模拟 Http 请求的功能。
包含Mock Objects, TestContext Framework, Spring MVC Test, WebTestClient。
对应的源码模块如下:
为什么用Spring?
那么为什么用Spring呢?来看看官网对这个问题的回答
最重要的体现在它能做什么,这是Spring的核心所在
且官方对此专门对此做了详细介绍,感兴趣可以看下
学习Spring时参考哪些资料呢?
非常负责任的告诉你,最好最全的资料在Spring的官网,Spring能成为最主要的企业开发框架,文档和生态体系也做的很好;这里介绍下如何获取官方的学习资源。@pdai
Spring 的官方项目和教程
官方的项目和教程,地址在这里,在学习Spring时,一定要把它当做生态体系,而是不是一个简单的开发框架。
Spring 的归档文档
官方提供了系统性的文档的FTP,你可以在这里找到所有历史版本的PDF/HTML版本。
可以看到很多系统性的文档,包括上面引用的图,
Spring 的官方Github
Spring官方的GitHub在这里,它包含着Spring-framework的源码,如果你感兴趣,可以从这里clone代码进行阅读。
更多文章
首先, 从Spring框架的整体架构和组成对整体框架有个认知。
- Spring是什么?它是怎么诞生的?有哪些主要的组件和核心功能呢? 本文通过这几个问题帮助你构筑Spring和Spring Framework的整体认知。
其次,通过案例引出Spring的核心(IoC和AOP),同时对IoC和AOP进行案例使用分析。
- 上文中我们简单介绍了Spring和Spring Framework的组件,那么这些Spring Framework组件是如何配合工作的呢?本文主要承接上文,向你展示Spring Framework组件的典型应用场景和基于这个场景设计出的简单案例,并以此引出Spring的核心要点,比如IOC和AOP等;在此基础上还引入了不同的配置方式, 如XML,Java配置和注解方式的差异。
- 在Spring基础 - Spring简单例子引入Spring的核心中向你展示了IoC的基础含义,同时以此发散了一些IoC相关知识点; 本节将在此基础上进一步解读IOC的含义以及IOC的使用方式
- 在Spring基础 - Spring简单例子引入Spring的核心中向你展示了AOP的基础含义,同时以此发散了一些AOP相关知识点; 本节将在此基础上进一步解读AOP的含义以及AOP的使用方式。
基于Spring框架和IOC,AOP的基础,为构建上层web应用,需要进一步学习SpringMVC。
- 前文我们介绍了Spring框架和Spring框架中最为重要的两个技术点(IOC和AOP),那我们如何更好的构建上层的应用呢(比如web 应用),这便是SpringMVC;Spring MVC是Spring在Spring Container Core和AOP等技术基础上,遵循上述Web MVC的规范推出的web开发框架,目的是为了简化Java栈的web开发。 本文主要介绍SpringMVC的请求流程和基础案例的编写和运行。
Spring进阶 - IoC,AOP以及SpringMVC的源码分析
- 在对IoC有了初步的认知后,我们开始对IOC的实现原理进行深入理解。本文将帮助你站在设计者的角度去看IOC最顶层的结构设计
- 上文,我们看了IOC设计要点和设计结构;紧接着这篇,我们可以看下源码的实现了:Spring如何实现将资源配置(以xml配置为例)通过加载,解析,生成BeanDefination并注册到IoC容器中的
- 上文,我们看了IOC设计要点和设计结构;以及Spring如何实现将资源配置(以xml配置为例)通过加载,解析,生成BeanDefination并注册到IoC容器中的;容器中存放的是Bean的定义即BeanDefinition放到beanDefinitionMap中,本质上是一个
ConcurrentHashMap<String, Object>
;并且BeanDefinition接口中包含了这个类的Class信息以及是否是单例等。那么如何从BeanDefinition中实例化Bean对象呢,这是本文主要研究的内容?
- 前文,我们分析了Spring IOC的初始化过程和Bean的生命周期等,而Spring AOP也是基于IOC的Bean加载来实现的。本文主要介绍Spring AOP原理解析的切面实现过程(将切面类的所有切面方法根据使用的注解生成对应Advice,并将Advice连同切入点匹配器和切面类等信息一并封装到Advisor,为后续交给代理增强实现做准备的过程)。
- 上文我们介绍了Spring AOP原理解析的切面实现过程(将切面类的所有切面方法根据使用的注解生成对应Advice,并将Advice连同切入点匹配器和切面类等信息一并封装到Advisor)。本文在此基础上继续介绍,代理(cglib代理和JDK代理)的实现过程。
- 我们在前文中已经介绍了SpringAOP的切面实现和创建动态代理的过程,那么动态代理是如何工作的呢?本文主要介绍Cglib动态代理的案例和SpringAOP实现的原理。
- 上文我们学习了SpringAOP Cglib动态代理的实现,本文主要是SpringAOP JDK动态代理的案例和实现部分。
- 前文我们有了IOC的源码基础以及SpringMVC的基础,我们便可以进一步深入理解SpringMVC主要实现原理,包含DispatcherServlet的初始化过程和DispatcherServlet处理请求的过程的源码解析。本文是第一篇:DispatcherServlet的初始化过程的源码解析。
- 前文我们有了IOC的源码基础以及SpringMVC的基础,我们便可以进一步深入理解SpringMVC主要实现原理,包含DispatcherServlet的初始化过程和DispatcherServlet处理请求的过程的源码解析。本文是第二篇:DispatcherServlet处理请求的过程的源码解析。
以上是关于Spring JdbcTemplate.batchUpdate()的主要内容,如果未能解决你的问题,请参考以下文章
Spring全家桶笔记:Spring+Spring Boot+Spring Cloud+Spring MVC
学习笔记——Spring简介;Spring搭建步骤;Spring的特性;Spring中getBean三种方式;Spring中的标签
Spring框架--Spring事务管理和Spring事务传播行为