Spring Batch 写数据库教程

Spring Batch 写数据库教程

上文我们学习如何读数据库,本文我们看如何通过Spring Batch写数据库。

1.需求及环境准备

1.1. 示例需求说明

需要实现把在线学习系统中的学生信息通过Srping job写入数据库,单个学生信息类如下:学生姓名、电子邮件、已购学习包。写数据库之前,我们需要提供输入数据组件。本例我们使用StudentDto对象,其包括单个学生信息:

@Data
public class StudentDTO {
 
    private String emailAddress;
    private String name;
    private String purchasedPackage;
}

下面开始配置应用上下文。

1.2. 配置应用上下文

在配置写数据库ItemWriter对象之前,需要先配置ItemWriter bean,有两种方式:

1)、如果使用Spring Framework,需要下列几个步骤:

  • 在应用上下文配置类中增加jdbcTemplate() 方法.

  • 确保jdbcTemplate() 方法返回 NamedParameterJdbcTemplate 对象并带有DataSource对象作为参数.

  • 在方法上增加@Bean 注解.

  • 实现方法并返回NamedParameterJdbcTemplate 对象.

部分对面如下:

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
 
import javax.sql.DataSource;
import java.util.Properties;
 
@Configuration
public class PersistenceContext {
 
    @Bean(destroyMethod = "close")
    DataSource dataSource(Environment env) {
        HikariConfig dataSourceConfig = new HikariConfig();
 
        dataSourceConfig.setDriverClassName(env.getRequiredProperty("db.driver"));
        dataSourceConfig.setJdbcUrl(env.getRequiredProperty("db.url"));
        dataSourceConfig.setUsername(env.getRequiredProperty("db.username"));
        dataSourceConfig.setPassword(env.getRequiredProperty("db.password"));
 
        return new HikariDataSource(dataSourceConfig);
    }
     
    @Bean
    NamedParameterJdbcTemplate jdbcTemplate(DataSource dataSource) {
        return new NamedParameterJdbcTemplate(dataSource);
    }
}

2)、如果使用Spring Boot,而且还没有禁用它的自动配置特性,那么我们就不必对配置进行任何更改,因为Spring Boot同时配置了JdbcTemplate和NamedParameterJdbcTemplate bean。

下面继续配置ItemWriter,负责写信息入库。

2. 通过jdbc写数据库

通过下面几个步骤配置ItemWriter:

第一步创建配置类,其中包括Spring job流程描述。创建CsvFileToDatabaseJobConfig 类并增加注解 @Configuration。对应代码如下:

import org.springframework.context.annotation.Configuration;
 
@Configuration
public class CsvFileToDatabaseJobConfig {
 
}

第二步创建方法配置ItemWriter bean,通过下面几步实现:

  • 在配置类中增加方法,确保方法返回ItemWriter 对象.

  • 确保方法带有 DataSource 和 NamedParameterJdbcTemplate 对象作为参数.

  • 暂时通过返回null实现方法.

增加方法后CsvFileToDatabaseJobConfig类代码如下:

import org.springframework.batch.item.ItemWriter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
 
import javax.sql.DataSource;
 
@Configuration
public class CsvFileToDatabaseJobConfig {
     
    @Bean
    ItemWriter<StudentDTO> csvFileDatabaseItemWriter(DataSource dataSource, 
                                                     NamedParameterJdbcTemplate jdbcTemplate) {
        return null;
    }
}

第三步创建JdbcBatchItemWriter对象,设置数据源和jdbcTemplate,确保方法返回该对象。最终CsvFileToDatabaseJobConfig类csvFileDatabaseItemWriter方法的完整代码如下:

import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.database.JdbcBatchItemWriter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
 
import javax.sql.DataSource;
 
@Configuration
public class CsvFileToDatabaseJobConfig {
 
    @Bean
    ItemWriter<StudentDTO> csvFileDatabaseItemWriter(DataSource dataSource, 
                                                     NamedParameterJdbcTemplate jdbcTemplate) {
        JdbcBatchItemWriter<StudentDTO> databaseItemWriter = new JdbcBatchItemWriter<>();
        databaseItemWriter.setDataSource(dataSource);
        databaseItemWriter.setJdbcTemplate(jdbcTemplate);
         
        return databaseItemWriter;
    }
}

下面配置插入数据库的INSERT语句。可以使用两者策略制定INSERT语句的参数,两者配置有差异。下面首先看看索引参数。

2.1. 索引参数

索引参数配置包括下面几步:

第一步创建出入student表的INSERT语句,使用常量属性保存INSERT语句并确保JdbcBatchItemWriter 对象使用该常量,CsvFileToDatabaseJobConfig代码如下:

import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.database.JdbcBatchItemWriter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
 
import javax.sql.DataSource;
 
@Configuration
public class CsvFileToDatabaseJobConfig {
 
    private static final String QUERY_INSERT_STUDENT = "INSERT " +
            "INTO students(email_address, name, purchased_package) " +
            "VALUES (?, ?, ?)";
 
    @Bean
    ItemWriter<StudentDTO> csvFileDatabaseItemWriter(DataSource dataSource,
                                                     NamedParameterJdbcTemplate jdbcTemplate) {
        JdbcBatchItemWriter<StudentDTO> databaseItemWriter = new JdbcBatchItemWriter<>();
        databaseItemWriter.setDataSource(dataSource);
        databaseItemWriter.setJdbcTemplate(jdbcTemplate);
 
        databaseItemWriter.setSql(QUERY_INSERT_STUDENT);
 
        return databaseItemWriter;
    }
}

第二步创建实现 ItemPreparedStatementSetter接口的类,该类负责给PreparedStatement 对象设置实际参数值,通过实现setValues方法实现。主要包括下面两步:

  • 创建实现ItemPreparedStatementSetter接口的类,并设置T类型为StudentDTO。
  • 实现setValues方法并按顺序配置参数值: emailAddress, name, purchasedPackage.

完整代码如下:

import org.springframework.batch.item.database.ItemPreparedStatementSetter;
 
import java.sql.PreparedStatement;
import java.sql.SQLException;
 
final class StudentPreparedStatementSetter implements ItemPreparedStatementSetter<StudentDTO> {
 
    @Override
    public void setValues(StudentDTO student, 
                          PreparedStatement preparedStatement) throws SQLException {
        preparedStatement.setString(1, student.getEmailAddress());
        preparedStatement.setString(2, student.getName());
        preparedStatement.setString(3, student.getPurchasedPackage());
    }
}

第三步确保JdbcBatchItemWriter 使用StudentPreparedStatementSetter。确保在执行INSERT语句时实际参数值被正确设置。
正确配置ItemPreparedStatementSetter 对象后,配置类的CsvFileToDatabaseJobConfig代码如下:

import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.database.ItemPreparedStatementSetter;
import org.springframework.batch.item.database.JdbcBatchItemWriter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
 
import javax.sql.DataSource;
 
@Configuration
public class CsvFileToDatabaseJobConfig {
 
    private static final String QUERY_INSERT_STUDENT = "INSERT " +
            "INTO students(email_address, name, purchased_package) " +
            "VALUES (?, ?, ?)";
 
    @Bean
    ItemWriter<StudentDTO> csvFileDatabaseItemWriter(DataSource dataSource,
                                                     NamedParameterJdbcTemplate jdbcTemplate) {
        JdbcBatchItemWriter<StudentDTO> databaseItemWriter = new JdbcBatchItemWriter<>();
        databaseItemWriter.setDataSource(dataSource);
        databaseItemWriter.setJdbcTemplate(jdbcTemplate);
 
        databaseItemWriter.setSql(QUERY_INSERT_STUDENT);
 
        ItemPreparedStatementSetter<StudentDTO> valueSetter = 
                new StudentPreparedStatementSetter();
        databaseItemWriter.setItemPreparedStatementSetter(valueSetter);
 
        return databaseItemWriter;
    }
}

通过上面几步就完成了ItemWriter 的配置,通过INSERT语句和索引参数实现在数据库中插入信息。

2.2. 命名参数

使用命名需要下面几个步骤进行配置:

第一步使用命名参数创建插入表的INSERT语句。使用命名参数的名称应该和StudentDto类属性名称保持一致。然后定义常量保存INSERT语句并确保JdbcBatchItemWriter 使用该常量,请看CsvFileToDatabaseJobConfig配置代码:

import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.database.JdbcBatchItemWriter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
 
import javax.sql.DataSource;
 
@Configuration
public class CsvFileToDatabaseJobConfig {
     
    private static final String QUERY_INSERT_STUDENT = "INSERT " +
            "INTO students(email_address, name, purchased_package) " +
            "VALUES (:emailAddress, :name, :purchasedPackage)";
     
    @Bean
    ItemWriter<StudentDTO> csvFileDatabaseItemWriter(DataSource dataSource, 
                                                     NamedParameterJdbcTemplate jdbcTemplate) {
        JdbcBatchItemWriter<StudentDTO> databaseItemWriter = new JdbcBatchItemWriter<>();
        databaseItemWriter.setDataSource(dataSource);
        databaseItemWriter.setJdbcTemplate(jdbcTemplate);
 
        databaseItemWriter.setSql(QUERY_INSERT_STUDENT);
 
        return databaseItemWriter;
    }
}

第二步配置ItemSqlParameterSourceProvider 对象,JdbcBatchItemWriter 对象使用该对象获得SqlParameterSource 对象引用,用于获取命名参数的值。

因为命名参数名称与StudentDTO名称一致,可以直接使用BeanPropertyItemSqlParameterSourceProvider 类实现。
配置完使用ItemSqlParameterSourceProvider 对象后,CsvFileToDatabaseJobConfig代码如下:

import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.database.BeanPropertyItemSqlParameterSourceProvider;
import org.springframework.batch.item.database.ItemSqlParameterSourceProvider;
import org.springframework.batch.item.database.JdbcBatchItemWriter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
 
import javax.sql.DataSource;
 
@Configuration
public class CsvFileToDatabaseJobConfig {
     
    private static final String QUERY_INSERT_STUDENT = "INSERT " +
            "INTO students(email_address, name, purchased_package) " +
            "VALUES (:emailAddress, :name, :purchasedPackage)";
     
    @Bean
    ItemWriter<StudentDTO> csvFileDatabaseItemWriter(DataSource dataSource, 
                                                     NamedParameterJdbcTemplate jdbcTemplate) {
        JdbcBatchItemWriter<StudentDTO> databaseItemWriter = new JdbcBatchItemWriter<>();
        databaseItemWriter.setDataSource(dataSource);
        databaseItemWriter.setJdbcTemplate(jdbcTemplate);
 
        databaseItemWriter.setSql(QUERY_INSERT_STUDENT);
 
        ItemSqlParameterSourceProvider<StudentDTO> paramProvider = 
                new BeanPropertyItemSqlParameterSourceProvider<>();
        databaseItemWriter.setItemSqlParameterSourceProvider(paramProvider);
 
        return databaseItemWriter;
    }
}

这就完成了命名参数方式配置。

3.总结

本文介绍了Spring batch写数据库,通过创建JdbcBatchItemWriter类。如果使用索引参数需要 ItemPreparedStatementSetter 接口,而使用命名参数需要实现ItemSqlParameterSourceProvider接口。如果使用命名参数且名称与DTO属性名称相同可以使用 BeanPropertyItemSqlParameterSourceProvider类。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Batch 的作用是实现批处理任务,其中涉及到对数据库的读操作。因此,在使用 Spring Batch 时,需要先创建相应的数据库表来存储批处理任务的信息。以下是 Spring Batch数据库脚本: ``` CREATE TABLE BATCH_JOB_INSTANCE ( JOB_INSTANCE_ID BIGINT NOT NULL PRIMARY KEY , VERSION BIGINT, JOB_NAME VARCHAR(100) NOT NULL, JOB_KEY VARCHAR(32) NOT NULL, constraint JOB_INST_UN unique (JOB_NAME, JOB_KEY) ) ; CREATE TABLE BATCH_JOB_EXECUTION ( JOB_EXECUTION_ID BIGINT NOT NULL PRIMARY KEY , VERSION BIGINT NOT NULL, JOB_INSTANCE_ID BIGINT NOT NULL, CREATE_TIME TIMESTAMP NOT NULL, START_TIME TIMESTAMP DEFAULT NULL , END_TIME TIMESTAMP DEFAULT NULL , STATUS VARCHAR(10) , EXIT_CODE VARCHAR(2500) , EXIT_MESSAGE VARCHAR(2500) , LAST_UPDATED TIMESTAMP NOT NULL, JOB_CONFIGURATION_LOCATION VARCHAR(2500) NULL, constraint JOB_INST_EXEC_FK foreign key (JOB_INSTANCE_ID) references BATCH_JOB_INSTANCE(JOB_INSTANCE_ID) ) ; CREATE TABLE BATCH_STEP_EXECUTION ( STEP_EXECUTION_ID BIGINT NOT NULL PRIMARY KEY , VERSION BIGINT NOT NULL, STEP_NAME VARCHAR(100) NOT NULL, JOB_EXECUTION_ID BIGINT NOT NULL, START_TIME TIMESTAMP NOT NULL , END_TIME TIMESTAMP DEFAULT NULL , STATUS VARCHAR(10) , COMMIT_COUNT BIGINT , READ_COUNT BIGINT , FILTER_COUNT BIGINT , WRITE_COUNT BIGINT , READ_SKIP_COUNT BIGINT , WRITE_SKIP_COUNT BIGINT , PROCESS_SKIP_COUNT BIGINT , ROLLBACK_COUNT BIGINT , EXIT_CODE VARCHAR(2500) , EXIT_MESSAGE VARCHAR(2500) , LAST_UPDATED TIMESTAMP NOT NULL, constraint JOB_EXEC_STEP_FK foreign key (JOB_EXECUTION_ID) references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID) ) ; CREATE TABLE BATCH_JOB_EXECUTION_PARAMS ( JOB_EXECUTION_ID BIGINT NOT NULL , TYPE_CD VARCHAR(6) NOT NULL , KEY_NAME VARCHAR(100) NOT NULL , STRING_VAL VARCHAR(250) , DATE_VAL TIMESTAMP DEFAULT NULL , LONG_VAL BIGINT , DOUBLE_VAL DOUBLE PRECISION , IDENTIFYING CHAR(1) NOT NULL , constraint JOB_EXEC_PARAMS_FK foreign key (JOB_EXECUTION_ID) references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID) ) ; CREATE TABLE BATCH_STEP_EXECUTION_CONTEXT ( STEP_EXECUTION_ID BIGINT NOT NULL PRIMARY KEY, SHORT_CONTEXT VARCHAR(2500) NOT NULL, SERIALIZED_CONTEXT TEXT , constraint STEP_EXEC_CTX_FK foreign key (STEP_EXECUTION_ID) references BATCH_STEP_EXECUTION(STEP_EXECUTION_ID) ) ; CREATE TABLE BATCH_JOB_EXECUTION_CONTEXT ( JOB_EXECUTION_ID PRIMARY KEY, SHORT_CONTEXT VARCHAR(2500) NOT NULL, SERIALIZED_CONTEXT TEXT , constraint JOB_EXEC_CTX_FK foreign key (JOB_EXECUTION_ID) references BATCH_JOB_EXECUTION(JOB_EXECUTION_ID) ) ; CREATE TABLE BATCH_STEP_EXECUTION_SEQ ( ID BIGINT NOT NULL, constraint STEP_EXECUTION_SEQ_PK primary key (ID) ) ; INSERT INTO BATCH_STEP_EXECUTION_SEQ values(0); CREATE TABLE BATCH_JOB_SEQ ( ID BIGINT NOT NULL, constraint JOB_SEQ_PK primary key (ID) ) ; INSERT INTO BATCH_JOB_SEQ values(0); CREATE TABLE BATCH_JOB_EXECUTION_SEQ ( ID BIGINT NOT NULL, constraint JOB_EXECUTION_SEQ_PK primary key (ID) ) ; INSERT INTO BATCH_JOB_EXECUTION_SEQ values(0); CREATE TABLE BATCH_JOB_PARAMS ( JOB_INSTANCE_ID BIGINT NOT NULL , TYPE_CD VARCHAR(6) NOT NULL , KEY_NAME VARCHAR(100) NOT NULL , STRING_VAL VARCHAR(250) , DATE_VAL TIMESTAMP DEFAULT NULL , LONG_VAL BIGINT , DOUBLE_VAL DOUBLE PRECISION , IDENTIFYING CHAR(1) NOT NULL , constraint JOB_INST_PARAMS_FK foreign key (JOB_INSTANCE_ID) references BATCH_JOB_INSTANCE(JOB_INSTANCE_ID) ) ; ``` 这些脚本将创建 Spring Batch 中使用的所有表。在使用 Spring Batch 进行开发时,可以将这些脚本直接在数据库中执行,以创建相应的表。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值