如何基于已有Product ArrayList实现Spring Batch结合JPA/Hibernate批量保存
Spring Batch 处理内存中ArrayList并通过JPA批量保存
核心思路
跳过文件读取环节,直接用Spring Batch提供的ListItemReader读取内存中的ArrayList<Product>,配合JpaItemWriter完成批量持久化,中间可按需添加自定义处理器做数据校验/转换。
依赖准备
确保项目依赖包含Spring Batch和Spring Data JPA(以Maven为例):
<dependencies> <!-- Spring Batch 核心依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-batch</artifactId> </dependency> <!-- Spring Data JPA --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <!-- 数据库驱动,根据实际使用的数据库替换 --> <dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <scope>runtime</scope> </dependency> </dependencies>
1. Product实体类示例
假设你已有如下实体类(适配JPA规范):
import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import lombok.Data; @Entity @Data public class Product { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; private Double price; // 其他业务字段及getter/setter(Lombok @Data可自动生成) }
2. 配置自定义ItemReader
用Spring Batch内置的ListItemReader直接读取内存列表,无需自定义Reader实现:
import org.springframework.batch.item.ItemReader; import org.springframework.batch.item.support.ListItemReader; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.ArrayList; import java.util.List; @Configuration public class BatchConfig { // 替换为你实际的Product集合,可从业务层注入或动态获取 private List<Product> getExistingProductList() { List<Product> products = new ArrayList<>(); products.add(new Product(null, "无线耳机", 399.0)); products.add(new Product(null, "智能手表", 1299.0)); return products; } @Bean public ItemReader<Product> productItemReader() { return new ListItemReader<>(getExistingProductList()); } }
如果集合是动态生成的(比如从接口或数据库查询),可通过StepExecutionListener在步骤启动时加载数据,避免硬编码。
3. 可选:自定义数据处理器
如需对数据做校验、转换,实现ItemProcessor:
import org.springframework.batch.item.ItemProcessor; public class ProductItemProcessor implements ItemProcessor<Product, Product> { @Override public Product process(Product product) throws Exception { // 示例:校正非法价格 if (product.getPrice() < 0) { product.setPrice(0.0); } // 可添加补全默认值、格式转换等逻辑 return product; } }
在配置类中注册处理器Bean:
@Bean public ItemProcessor<Product, Product> productItemProcessor() { return new ProductItemProcessor(); }
4. 配置JpaItemWriter实现批量保存
使用Spring Batch提供的JpaItemWriter,直接对接JPA完成批量持久化:
import org.springframework.batch.item.database.JpaItemWriter; import jakarta.persistence.EntityManagerFactory; import org.springframework.context.annotation.Bean; @Bean public JpaItemWriter<Product> productJpaItemWriter(EntityManagerFactory entityManagerFactory) { JpaItemWriter<Product> writer = new JpaItemWriter<>(); writer.setEntityManagerFactory(entityManagerFactory); return writer; }
5. 组装Job和Step
将Reader、Processor(可选)、Writer组合成Step,再构建Job:
import org.springframework.batch.core.Job; import org.springframework.batch.core.Step; import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; import org.springframework.batch.core.job.builder.JobBuilder; import org.springframework.batch.core.repository.JobRepository; import org.springframework.batch.core.step.builder.StepBuilder; import org.springframework.context.annotation.Bean; import org.springframework.transaction.PlatformTransactionManager; @EnableBatchProcessing @Configuration public class BatchConfig { // 上述Reader、Processor、Writer Bean... @Bean public Step productBatchStep(JobRepository jobRepository, PlatformTransactionManager transactionManager, ItemReader<Product> productItemReader, ItemProcessor<Product, Product> productItemProcessor, JpaItemWriter<Product> productJpaItemWriter) { return new StepBuilder("productBatchStep", jobRepository) .<Product, Product>chunk(100) // 每100条提交一次事务,根据数据库性能调整 .reader(productItemReader) .processor(productItemProcessor) // 无需处理器可删除此行 .writer(productJpaItemWriter) .transactionManager(transactionManager) .build(); } @Bean public Job productBatchJob(JobRepository jobRepository, Step productBatchStep) { return new JobBuilder("productBatchJob", jobRepository) .start(productBatchStep) .build(); } }
6. 启动Batch Job
通过CommandLineRunner在项目启动时自动执行,或通过Controller/定时任务触发:
import org.springframework.batch.core.Job; import org.springframework.batch.core.JobParameters; import org.springframework.batch.core.JobParametersBuilder; import org.springframework.batch.core.launch.JobLauncher; import org.springframework.boot.CommandLineRunner; import org.springframework.stereotype.Component; @Component public class BatchJobStarter implements CommandLineRunner { private final JobLauncher jobLauncher; private final Job productBatchJob; public BatchJobStarter(JobLauncher jobLauncher, Job productBatchJob) { this.jobLauncher = jobLauncher; this.productBatchJob = productBatchJob; } @Override public void run(String... args) throws Exception { JobParameters jobParameters = new JobParametersBuilder() .addLong("executeTime", System.currentTimeMillis()) // 确保每次Job参数唯一,避免重复执行 .toJobParameters(); jobLauncher.run(productBatchJob, jobParameters); } }
关键优化配置
在application.properties中添加Hibernate批量操作配置,提升插入性能:
# Hibernate批量插入配置 spring.jpa.properties.hibernate.jdbc.batch_size=100 spring.jpa.properties.hibernate.order_inserts=true spring.jpa.properties.hibernate.order_updates=true
内容的提问来源于stack exchange,提问作者Vishvajeet w
相关产品推荐
相关产品推荐

