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类。
本文参考链接:https://blog.csdn.net/neweastsun/article/details/101980066