问题
I can read and insert in the DB if the csv file has only lines starting with ORD but if the file is showing as below, mixed with different rows, I can do the mapping but the problem is what I'm using with the type of object for the chunk, as it takes one type of class.
I want to map each row and then accordingly insert into the DB based on the first three characters, if the row starts with ORD then insert in Order table if starts with DET then insert in Detail table, my coding below show where I have reached so far, is there any help that you can further provide me please
Note that file structure is always showing orders then items related to this order.
Here is the csv file format:
ORD,02013872,12345,,P,,,HYD800,,,,,
DET,1.0,100,5.0,,31Jan2017,,,,,
DET,2.0,120001,10.0,,25Jan2017,,,,,
ORD,02013872,12345,,P,,,HYD800,,,,,
DET,1.0,100,5.0,,31Jan2017,,,,,
DET,2.0,120001,10.0,,25Jan2017,,,,,
ORD,02013872,12345,,P,,,HYD800,,,,,
DET,1.0,100,5.0,,31Jan2017,,,,,
DET,2.0,120001,10.0,,25Jan2017,,,,,
Here is the code that I have so far:
@Entity
public class OrderDetail {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String branchCode;
private String ord;
private String eiclientNumber;
private String clientOrderNumber;
private String consigneeP;
private String paymentTerms;
private String earliestShipDate;
private String latestShipDate;
private String consigneeCode;
private String billToCode;
private String thirdPartyBillToCustomerNo;
private String preferredCarrier;
private String usd1;
private String usd2;
@ManyToMany(mappedBy = "orderDetails")
private Set<ItemDetail> itemDetails = new HashSet<>();
}
@Entity
public class ItemDetail {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String branchCode;
private String ordNo;
private String detail;
private String lineNumber;
private String skuNumber;
private String qty;
private String lotNo;
private String receiptPo;
private String usd1;
private String usd2;
private String usd3;
private String usd4;
@ManyToMany
@JoinTable(name = "order_item", joinColumns = @JoinColumn(name = "item_id"),
inverseJoinColumns = @JoinColumn(name = "order_id"))
private Set<OrderDetail> orderDetails = new HashSet<>();
}
@Configuration
@EnableBatchProcessing
public class BatchConfig {
@Autowired
private JobBuilderFactory jobBuilderFactory;
@Autowired
private StepBuilderFactory stepBuilderFactory;
@Bean
public Step sampleStep(JdbcBatchItemWriter<OrderDetail> writer) throws Exception {
return stepBuilderFactory.get("sampleStep")
.<OrderDetail,OrderDetail>chunk(5)
.reader(reader(null))
.writer(writer)
.build();
}
@Bean
public Job importUserJob(JobCompletionNotificationListener listener, Step sampleStep) {
return jobBuilderFactory.get("orderJob")
.incrementer(new RunIdIncrementer())
.listener(listener)
.flow(sampleStep)
.end()
.build();
}
@Bean
@StepScope
public JdbcBatchItemWriter<OrderDetail> writer(DataSource dataSource,@Value("#{jobParameters[file_path]}") String filePath) {
final FileSystemResource fileResource = new FileSystemResource(filePath);
System.out.println("Branch code is : " + fileResource.getFilename().substring(5,8)); //getting the branch code from the path to insert it in table order details
String branchCode = fileResource.getFilename().substring(5,8);
return new JdbcBatchItemWriterBuilder<OrderDetail>()
.itemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<>())
.sql("INSERT INTO order_detail (ord, branch_code, eiclient_number, client_order_number, consigneep, payment_terms, earliest_ship_date, latest_ship_date, consignee_code, bill_to_code, third_party_bill_to_customer_no, preferred_carrier, usd1, usd2) " +
"VALUES (:ord, '"+branchCode+"', :eiclientNumber, :clientOrderNumber, :consigneeP, :paymentTerms, :earliestShipDate, :latestShipDate, :consigneeCode, :billToCode, :thirdPartyBillToCustomerNo, :preferredCarrier, :usd1, :usd2)")
/* .sql("INSERT INTO item_detail (ord_no, branch_code, detail, line_number, sku_number, qty, lot_no, receipt_po, usd1, usd2, usd3, usd4) " +
"VALUES (:ordNo, '"+branchCode+"', :detail, :lineNumber, :skuNumber, :qty, :lotNo, :receiptPo, :usd1, :usd2, :usd3, :usd4)")
*/
.dataSource(dataSource)
.build();
}
@Bean
@StepScope
public FlatFileItemReader reader(@Value("#{jobParameters[file_path]}") String filePath) throws Exception {
final FileSystemResource fileResource = new FileSystemResource(filePath);
return new FlatFileItemReaderBuilder()
.name("ordersItemReader")
.resource(fileResource)
.lineMapper(orderLineMapper())
/*.delimited()
.names(new String[]{"ord", "branchCode", "eiclientNumber", "clientOrderNumber", "consigneeP", "paymentTerms", "earliestShipDate", "latestShipDate", "consigneeCode", "billToCode", "thirdPartyBillToCustomerNo"})
.fieldSetMapper(new BeanWrapperFieldSetMapper<OrderDetail>() {{
setTargetType(OrderDetail.class);
}})*/
.build();
}
@Bean
public LineMapper orderLineMapper() throws Exception {
PatternMatchingCompositeLineMapper mapper = new PatternMatchingCompositeLineMapper();
Map<String, LineTokenizer> tokenizers = new HashMap<String, LineTokenizer>();
tokenizers.put("ORD*",orderTokenizer() );
tokenizers.put("DET*",orderItemTokenizer());
mapper.setTokenizers(tokenizers);
Map<String, FieldSetMapper> mappers = new HashMap<String, FieldSetMapper>();
mappers.put("ORD*", orderFieldSetMapper());
mappers.put("DET*", orderLineFieldSetMapper());
mapper.setFieldSetMappers(mappers);
return mapper;
}
@Bean
public LineTokenizer orderTokenizer() {
DelimitedLineTokenizer tokenizer = new DelimitedLineTokenizer(",");
tokenizer.setNames(new String[] { "ord", "eiclientNumber", "clientOrderNumber", "consigneeP", "paymentTerms", "earliestShipDate", "latestShipDate", "consigneeCode", "billToCode", "thirdPartyBillToCustomerNo", "preferredCarrier", "usd1","usd2"});
return tokenizer;
}
@Bean
public LineTokenizer orderItemTokenizer() {
DelimitedLineTokenizer tokenizer = new DelimitedLineTokenizer(",");
tokenizer.setNames(new String[] { "ordNo", "detail", "lineNumber", "skuNumber", "qty", "lotNo", "receiptPo", "usd1", "usd2", "usd3", "usd4"});
return tokenizer;
}
@Bean
public FieldSetMapper<OrderDetail> orderFieldSetMapper() throws Exception {
BeanWrapperFieldSetMapper<OrderDetail> mapper =
new BeanWrapperFieldSetMapper<OrderDetail>();
mapper.setPrototypeBeanName("orderDetail");
mapper.afterPropertiesSet();
return mapper;
}
@Bean
@Scope("prototype")
public OrderDetail orderDetail() {
return new OrderDetail();
}
}
来源:https://stackoverflow.com/questions/57557032/reading-csv-file-with-spring-batch-and-map-to-domain-objects-based-on-the-the-fi