在本文中,我們將演示如何使用 Spring Batch 從 Excel (.xls 或 .xlsx) 檔案讀取所有行並將其儲存到 Spring Boot 應用程式中的資料庫中。我們將介紹從讀取 Excel 檔案、將行轉換為Entity例項、將這些例項儲存到資料庫、記錄進度以及使用 cron 表示式安排批處理作業的整個過程。
前提:
確保您具有以下資訊:
- JDK 17 或更高版本
- Maven 或 Gradle
- Spring Boot 3.2.7 或更高版本
- H2 或任何其他資料庫
- Apache POI 用於讀取 Excel 檔案
pom.xml:
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-batch</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.springframework.batch.extensions</groupId> <artifactId>spring-batch-excel</artifactId> <version>0.1.1</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>5.2.5</version> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>runtime</scope> </dependency> </dependencies>
|
示例Excel 檔案包含員工列表,每行代表單個員工的詳細資訊。Excel 檔案中的列直接對應於實體類中的欄位Employee:
- Name名稱:此列對映到實體name中的欄位Employee。
- Department部門:此列對映到實體department中的欄位Employee。
- Email電子郵件:此列對映到實體email中的欄位Employee。
實體Employee類定義如下:
@Entity public class Employee { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; private String department; private String email; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDepartment() { return department; } public void setDepartment(String department) { this.department = department; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } @Override public String toString() { return <font>"Employee{" + "id=" + id + ", name=" + name + ", department=" + department + ", email=" + email + '}'; } }
|
為實體Employee建立一個儲存庫介面。
@Repository public interface EmployeeRepository extends JpaRepository{ }
|
使用 PoiItemReader 實現 Excel 閱讀器
Spring Batch Extension 提供PoiItemReader讀取 Excel 檔案的功能。在這裡,我們將配置它來處理員工數
@Configuration public class PoiReader { @Value(<font>"${excel.file.path}") private String filePath; @Bean public ItemReader<Employee> employeeReader() { PoiItemReader<Employee> reader = new PoiItemReader<>(); reader.setResource(new ClassPathResource(filePath)); reader.setLinesToSkip(1); reader.setRowMapper(new BeanWrapperRowMapper<Employee>() { { setTargetType(Employee.class); } }); reader.setName("employeeReader"); return reader; } }
|
- @Value註釋從應用程式屬性中注入檔案路徑(例如excel.file.path=employees.xlsx)。
- PoiItemReader將 Excel 檔案位置配置為 ClasspathResource。
- BeanWrapperRowMapper自動將列名對映到類中相應的欄位Employee。
- setLinesToSkip(1)確保跳過標題行。
使用 JpaRepository 儲存到資料庫
接下來,我們將利用 Spring Data JPA EmployeeRepository將處理後的員工資料儲存到資料庫。
@Bean public ItemWriter employeeWriter(EmployeeRepository repository) { return items -> { for (Employee employee : items) { repository.save(employee); System.out.println(<font>"Employee saved: " + employee.getName()); } }; }
|
該 ItemWriter 會遍歷僱員物件列表,並使用 EmployeeRepository 儲存這些物件。
配置Spring Batch作業
以下是本文中用於配置 Spring Batch 作業的完整示例程式碼,該作業從 Excel 檔案讀取員工資料、處理資料並將其寫入資料庫。每個步驟都分解為更小的元件 - ItemReader、ItemProcessor 和 ItemWriter。
@Configuration public class PoiReader { @Value(<font>"${excel.file.path}") private String filePath; private final JobRepository jobRepository; private final PlatformTransactionManager transactionManager; private final EmployeeRepository employeeRepository; public PoiReader(JobRepository jobRepository, EmployeeRepository employeeRepository, PlatformTransactionManager transactionManager) { this.jobRepository = jobRepository; this.transactionManager = transactionManager; this.employeeRepository = employeeRepository; } @Bean public ItemReader<Employee> employeeReader() { PoiItemReader<Employee> reader = new PoiItemReader<>(); reader.setResource(new ClassPathResource(filePath)); reader.setLinesToSkip(1); reader.setRowMapper(new BeanWrapperRowMapper<Employee>() { { setTargetType(Employee.class); } }); reader.setName("employeeReader"); return reader; } @Bean public ItemWriter<Employee> employeeWriter() { return items -> { for (Employee employee : items) { employeeRepository.save(employee); System.out.println("Employee saved: " + employee.getName()); } }; } @Bean public ItemProcessor<Employee, Employee> processor() { return employee -> { // Example processor logic<i> employee.setName(employee.getName()); System.out.println("Name: " + employee.getName() + ", Department: " + employee.getDepartment()); return employee; }; } @Bean public Step chunkProcessingStep() { var builder = new StepBuilder("chunkProcessingStep", jobRepository); return builder .<Employee, Employee>chunk(1, transactionManager) .reader(employeeReader()) .processor(processor()) .writer(employeeWriter()) .build(); } @Bean Job importUserJob(Step step1) { var builder = new JobBuilder("importUserJob", jobRepository); return builder .incrementer(new RunIdIncrementer()) .start(step1) .build(); } }
|
上述程式碼定義了一個 Spring Batch 配置,該配置使用 @Value 注入 Excel 檔案的路徑,還包括 JobRepository、EmployeeRepository 和 PlatformTransactionManager 的建構函式注入,它們分別用於管理作業執行、資料庫操作和事務管理。 該類定義了對批處理至關重要的幾個 Bean:
該類定義了對批處理至關重要的幾個bean:
- employeeReader(): 此 Bean 使用 PoiItemReader 從 Excel 檔案中讀取資料。 它會跳過標題行,並使用 BeanWrapperRowMapper 將每一行對映到僱員物件:
- employeeWriter(): 此 bean 使用 EmployeeRepository 將處理過的僱員物件寫入資料庫。
- Processor(): 此 Bean 處理每個僱員物件。 在此示例中,它會列印僱員的姓名和部門。
- chunkProcessingStep(): 它將讀取器、處理器和寫入器結合起來,以處理資料塊。
- importUserJob(): 此 Bean 將定義批處理作業本身,從定義的步驟開始,並使用 RunIdIncrementer 確保作業執行的唯一性。
排程批處理作業
一旦配置好批處理作業,下一步就是排程它在特定時間間隔執行。 Spring Boot 透過 @EnableScheduling 註解和 @Scheduled 註解提供了排程功能。 透過使用這些註解,我們可以輕鬆地排程批處理作業以固定的時間間隔執行,如每小時、每天或基於更復雜的 cron 表示式。
在我們的示例中,我們將排程批處理作業在每小時的頂部執行。 這樣就能確保每小時從 Excel 檔案讀取僱員資料並寫入資料庫。
@Configuration @EnableScheduling public class BatchScheduler { @Autowired private JobLauncher jobLauncher; @Autowired private Job importUserJob; @Scheduled(cron = <font>"0 0 * * * ?") // Run at the top of every hour<i> public void perform() throws Exception { jobLauncher.run(importUserJob, new JobParameters()); } }
|
上面的程式碼片段排程一個批處理任務在每小時的頂部執行。 該類使用 @EnableScheduling 進行註解,以啟用 Spring 的計劃任務執行功能。 它自動連線了 JobLauncher 和 Job Bean,以啟動和執行名為 importUserJob 的批處理任務。
@Scheduled(cron = "0 0 * * * ?") 註解指定了 perform() 方法應在每小時開始時執行,從而觸發批處理任務。
結論
在本文中,我們探討了如何實現 Spring Batch Excel 閱讀器,以便從 Excel 檔案中高效讀取員工資料並將其儲存到資料庫中。 我們介紹了從設定專案和定義實體到配置批處理作業和使用 cron 表示式排程的各個步驟。