Spring5参考指南
  • 简介
  • 前言
    • 1. “Spring”代表什么
    • 2. Spring和Spring框架的历史
    • 3. 设计哲学
    • 4. 反馈和贡献
    • 5. 开始
  • 核心技术
    • 1. IoC容器
      • 1.1 IoC容器和Beans介绍
      • 1.2 IoC容器概述
      • 1.3 Bean概述
      • 1.4 依赖
      • 1.5 Bean作用域
      • 1.6 自定义Bean
      • 1.7 Bean的继承
      • 1.8 容器扩展点
      • 1.9 基于注解的容器配置
      • 1.10 类路径扫描和托管组件
      • 1.11 使用JSR 330标准注解
      • 1.12 基于Java的容器配置
      • 1.13 环境抽象
      • 1.14 注册LoadTimeWeaver
      • 1.15 ApplicationContext的其他功能
      • 1.16 BeanFactory
    • 2.资源
      • 2.1介绍
      • 2.2资源接口
      • 2.3内置资源实现
      • 2.4ResourceLoader
      • 2.5ResourceLoaderAware接口
      • 2.6资源作为依赖
      • 2.7应用程序上下文和资源路径
    • 3.验证,数据绑定,和类型转换
      • 3.1使用Spring Validator接口
      • 3.2将代码解析为错误消息
      • 3.3bean操作和BeanWrapper
      • 3.4Spring类型转换
      • 3.5Spring字段格式化
      • 3.6配置全局Date和Time格式
      • 3.7Spring验证
    • 4.SpEL Spring表达式语言
      • 4.1求值
      • 4.2bean定义中的表达式
      • 4.3语言引用
    • 5.Spring AOP
      • 5.1什么是AOP
      • 5.1Spring AOP的能力和目标
      • 5.3AOP代理
      • 5.4@AspectJ 支持
      • 5.5基于Schema的AOP支持
      • 5.6选择要使用的AOP声明样式
      • 5.7混合Aspect类型
      • 5.8代理机制
      • 5.9程序创建@AspectJ代理
      • 5.10在Spring应用程序中使用AspectJ
      • 5.11更多资源
    • 6.Spring AOP APIs
      • 6.1Pointcut API
      • 6.2Advice API
      • 6.3Advisor API
      • 6.4使用ProxyFactoryBean来创建AOP代理
      • 6.5简介的代理定义
      • 6.6使用ProxyFactory创建AOP代理
      • 6.7操作被通知的对象
      • 6.8使用auto-proxy功能
      • 6.9使用TargetSource的实现
      • 6.10定义新的Advice Types
    • 7.Null-safety
    • 8.数据缓存和解码器
    • 9.附录
      • 9.1XML Schemas
      • 9.2创建XML Schemas
  • 测试
    • 1.Spring测试介绍
    • 2.单元测试
      • 2.1Mock Objects
      • 2.2单元测试支持类
    • 3.集成测试
      • 3.1概览
      • 3.2集成测试的目的
      • 3.3JDBC测试支持
      • 3.4注解
      • 3.5Spring TestContext框架
      • 3.6Spring MVC测试框架
      • 3.7WebTestClient
    • 4.更多资源
  • 数据访问
    • 1.事务管理
    • 2.DAO支持
    • 3.JDBC
      • 3.1选择JDBC数据库访问方法
      • 3.2包层次结构
      • 3.3使用JDBC核心类控制基本JDBC处理和错误处理
      • 3.4控制数据库连接
      • 3.5JDBC批处理操作
      • 3.6使用SimpleJdbc
      • 3.7将JDBC操作建模为Java对象
      • 3.8参数和数据值处理的常见问题
      • 3.9嵌入式数据库支持
      • 3.10初始化数据源
    • 4.ORM
      • 4.1Spring ORM介绍
      • 4.2ORM集成的一般注意事项
      • 4.3Hibernate
      • 4.4JPA
    • 5.使用Object-XML映射封装XML
  • Web Servlet
    • 1. Spring Web MVC
      • 1.1 DispatcherServlet
      • 1.2 Filters
      • 1.3 Controllers注解
      • 1.4 URI链接
      • 1.5 异步请求
      • 1.6 CORS
      • 1.7 Web Security
      • 1.8 HTTP Caching
      • 1.9 View技术
      • 1.10 MVC配置
      • 1.11 HTTP/2
    • 2. REST客户端
    • 3. 测试
    • 4. WebSockets
      • 4.1 WebSocket介绍
      • 4.2 WebSocket API
      • 4.3 SockJS Fallback
      • 4.4 STOMP
  • Web Reactive
    • 1.Spring WebFlux
      • 1.1 Overview
      • 1.2 Reactive Core
      • 1.3 DispatcherHandler
      • 1.4 Annotated Controllers
      • 1.5 Functional Endpoints
      • 1.6 URI Links
      • 1.7 CORS
      • 1.8 Web Security
      • 1.9 View Technologies
      • 1.10 HTTP Caching
      • 1.11 WebFlux Config
      • 1.12 HTTP/2
    • 2.WebClient
    • 3.WebSockets
    • 4.测试
    • 5.Reactive库
由 GitBook 提供支持
在本页
  • 3.5.1 使用JdbcTemplate的基本批处理操作
  • 3.5.2 对象列表的批处理操作
  • 3.5.3 具有多个批次的批次操作

这有帮助吗?

  1. 数据访问
  2. 3.JDBC

3.5JDBC批处理操作

如果将多个调用批处理到同一条准备好的语句,则大多数JDBC驱动程序都会提高性能。 通过将更新分组,可以限制到数据库的往返次数。

3.5.1 使用JdbcTemplate的基本批处理操作

你可以通过实现特殊接口的两个方法BatchPreparedStatementSetter并将该实现作为batchUpdate方法调用中的第二个参数传入来完成JdbcTemplate批处理。 你可以使用getBatchSize方法提供当前批处理的大小。 你可以使用setValues方法设置准备好的语句的参数值。 此方法称为你在getBatchSize调用中指定的次数。 以下示例根据列表中的条目更新actor表,并将整个列表用作批处理:

public class JdbcActorDao implements ActorDao {

    private JdbcTemplate jdbcTemplate;

    public void setDataSource(DataSource dataSource) {
        this.jdbcTemplate = new JdbcTemplate(dataSource);
    }

    public int[] batchUpdate(final List<Actor> actors) {
        return this.jdbcTemplate.batchUpdate(
                "update t_actor set first_name = ?, last_name = ? where id = ?",
                new BatchPreparedStatementSetter() {
                    public void setValues(PreparedStatement ps, int i) throws SQLException {
                        ps.setString(1, actors.get(i).getFirstName());
                        ps.setString(2, actors.get(i).getLastName());
                        ps.setLong(3, actors.get(i).getId().longValue());
                    }
                    public int getBatchSize() {
                        return actors.size();
                    }
                });
    }

    // ... additional methods
}

如果处理更新流或从文件读取,则可能具有首选的批处理大小,但最后一批可能没有该数量的条目。在这种情况下,可以使用InterruptibleBatchPreparedStatementSetter接口,该接口可在输入源耗尽后中断批处理。 isBatchExhausted方法使你可以发出批处理结束的信号。

3.5.2 对象列表的批处理操作

JdbcTemplate和NamedParameterJdbcTemplate都提供了另​​一种提供批处理更新的方式。无需实现特殊的批处理接口,而是将调用中的所有参数值作为列表提供。框架遍历这些值并使用内部的准备好的语句设置器。 API会有所不同,具体取决于你是否使用命名参数。对于命名参数,你提供一个SqlParameterSource数组,该批处理的每个成员都有一个条目。你可以使用SqlParameterSourceUtils.createBatch便捷方法创建此数组,传入一个bean样式的对象数组(带有与参数相对应的getter方法),字符串键的Map实例(包含对应的参数作为值),或者混合使用都。

以下示例显示了使用命名参数的批量更新:

public class JdbcActorDao implements ActorDao {

    private NamedParameterTemplate namedParameterJdbcTemplate;

    public void setDataSource(DataSource dataSource) {
        this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
    }

    public int[] batchUpdate(List<Actor> actors) {
        return this.namedParameterJdbcTemplate.batchUpdate(
                "update t_actor set first_name = :firstName, last_name = :lastName where id = :id",
                SqlParameterSourceUtils.createBatch(actors));
    }

    // ... additional methods
}

对于使用经典的SQL语句? 占位符,则传入包含包含更新值的对象数组的列表。 该对象数组在SQL语句中的每个占位符必须有一个条目,并且它们的顺序必须与SQL语句中定义的顺序相同。

以下示例与前面的示例相同,不同之处在于它使用经典的JDBC?占位符:

public class JdbcActorDao implements ActorDao {

    private JdbcTemplate jdbcTemplate;

    public void setDataSource(DataSource dataSource) {
        this.jdbcTemplate = new JdbcTemplate(dataSource);
    }

    public int[] batchUpdate(final List<Actor> actors) {
        List<Object[]> batch = new ArrayList<Object[]>();
        for (Actor actor : actors) {
            Object[] values = new Object[] {
                    actor.getFirstName(), actor.getLastName(), actor.getId()};
            batch.add(values);
        }
        return this.jdbcTemplate.batchUpdate(
                "update t_actor set first_name = ?, last_name = ? where id = ?",
                batch);
    }

    // ... additional methods
}

我们前面介绍的所有批处理更新方法都返回一个int数组,其中包含每个批处理条目的受影响行数。此计数由JDBC驱动程序报告。如果该计数不可用,则JDBC驱动程序将返回值-2。

在这种情况下,通过在基础PreparedStatement上自动设置值,需要从给定的Java类型派生每个值的对应JDBC类型。尽管这通常效果很好,但存在潜在的问题(例如,包含Map的空值)。在这种情况下,Spring默认情况下会调用ParameterMetaData.getParameterType,这对于JDBC驱动程序可能会很昂贵。如果遇到性能问题,应使用最新的驱动程序版本,并考虑将spring.jdbc.getParameterType.ignore属性设置为true(作为JVM系统属性或在类路径根目录中的spring.properties文件中)。 ,如Oracle 12c(SPR-16139)所述。

或者,你可以考虑通过“ BatchPreparedStatementSetter”(如前所示),通过为基于“ List ”的调用提供的显式类型数组,通过在服务器上的“ registerSqlType”调用来显式指定相应的JDBC类型。自定义“ MapSqlParameterSource”实例,或者通过“ BeanPropertySqlParameterSource”实例从Java声明的属性类型中获取SQL类型,即使对于null值也是如此。

3.5.3 具有多个批次的批次操作

前面的批处理更新示例处理的批处理过大,你想将它们分解成几个较小的批处理。 你可以通过多次调用batchUpdate方法来使用前面提到的方法来执行此操作,但是现在有了一个更方便的方法。 除了SQL语句外,此方法还包含一个对象集合,该对象包含参数,每个批处理要进行的更新次数以及一个ParameterizedPreparedStatementSetter来设置准备好的语句的参数值。 框架遍历提供的值,并将更新调用分成指定大小的批处理。

以下示例显示了使用100的批量大小的批量更新:

public class JdbcActorDao implements ActorDao {

    private JdbcTemplate jdbcTemplate;

    public void setDataSource(DataSource dataSource) {
        this.jdbcTemplate = new JdbcTemplate(dataSource);
    }

    public int[][] batchUpdate(final Collection<Actor> actors) {
        int[][] updateCounts = jdbcTemplate.batchUpdate(
                "update t_actor set first_name = ?, last_name = ? where id = ?",
                actors,
                100,
                new ParameterizedPreparedStatementSetter<Actor>() {
                    public void setValues(PreparedStatement ps, Actor argument) throws SQLException {
                        ps.setString(1, argument.getFirstName());
                        ps.setString(2, argument.getLastName());
                        ps.setLong(3, argument.getId().longValue());
                    }
                });
        return updateCounts;
    }

    // ... additional methods
}

此调用的批处理更新方法返回一个int数组数组,该数组包含每个批处理的数组条目以及每个更新受影响的行数的数组。 顶层数组的长度指示已执行的批处理数量,第二层数组的长度指示该批处理中的更新数量。 每个批次中的更新数量应该是为所有批次提供的批次大小(最后一个可能更少),这取决于所提供的更新对象的总数。 每个更新语句的更新计数是JDBC驱动程序报告的计数。 如果该计数不可用,则JDBC驱动程序将返回值-2。

上一页3.4控制数据库连接下一页3.6使用SimpleJdbc

最后更新于3年前

这有帮助吗?