Как автоматически обнаружить и сопоставить несколько форматов CSV в один объект без ненужного кода Java?MySql

Форум по Mysql
Ответить
Anonymous
 Как автоматически обнаружить и сопоставить несколько форматов CSV в один объект без ненужного кода Java?

Сообщение Anonymous »

Я создаю приложение Spring Boot 4.0.1, используя Spring Batch 6.0.1 для приема банковских транзакций из нескольких источников CSV (в частности, N26 и Revolut).
Проблема
Все файлы помещены в один и тот же каталог, но имеют разную структуру (= разные имена столбцов).
Моя цель — прочитать эти разнородные файлы и нормализовать их в единый объект базы данных, называемый, скажем, FinalTransaction.
Моя текущая стратегия
Я ищу самый «родной для Spring Batch» способ справиться с этим.
Мой код уже может обрабатывать транзакции N26 (на данный момент класс называется просто Transaction, потому что это именно то, что он поддерживает)
Транзакция.класс:

Код: Выделить всё

@Builder
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
@ToString
@Entity
@Table
public class Transaction {

@Id
@GeneratedValue
private Integer id; // optional, can be generated later

private LocalDate bookingDate;
private LocalDate valueDate;
private String partnerName;
private String partnerIban;
private String type;
private String paymentReference;
private String accountName;

private Double amount;
private Double originalAmount;
private String originalCurrency;
private Double exchangeRate;
private String category; // TODO: Should be enum
}
Я подумал, что было бы неплохо получить SchemaType непосредственно из API:
JobRestController.class:

Код: Выделить всё

@RestController
public class JobRestController {

@Autowired
private JobOperator jobOperator;

@Autowired
private Job transactionCategorizationJob;

@PostMapping("job/run")
ResponseEntity startJob(@RequestParam String schemaType, @RequestParam String fileName) throws JobInstanceAlreadyCompleteException, InvalidJobParametersException, JobExecutionAlreadyRunningException, JobRestartException {

// TODO: Make a cleaner validation
if(!schemaType.equals("n26") && !schemaType.equals("revolut")) {
return ResponseEntity.badRequest().body("Invalid schema type. The value must be either 'n26' or 'revolut'");
}

JobParameters jobParameters = new JobParametersBuilder()
.addString("schemaType", schemaType)
.addString("fileName", fileName)
.toJobParameters();
JobParameters params = new JobParametersBuilder()
.addLong("run.id", System.currentTimeMillis())
.addJobParameters(jobParameters)
.toJobParameters();

jobOperator.start(transactionCategorizationJob, params);

return ResponseEntity.ok("Transaction job started");
}
}
а затем выберите соответствующие столбцы в сопоставителе строк, но я не уверен, что это лучший подход:

TransactionLineMapper.class:

Код: Выделить всё

@StepScope // Necessary to get the schemaType
@Component
public class TransactionLineMapper extends DefaultLineMapper {

public TransactionLineMapper(
TransactionFieldSetMapper mapper,
CsvSchemas csvSchemas,
@Value("#{jobParameters['schemaType']}") String schemaType) {
super();

DelimitedLineTokenizer tokenizer = new DelimitedLineTokenizer();
tokenizer.setStrict(false);
setLineTokenizer(tokenizer);
setFieldSetMapper(mapper);
tokenizer.setNames(csvSchemas.getColumnNames(schemaType));
}

}
Сейчас я извлекаю имена столбцов из файла YAML. Это временно:

CsvSchema.class:

Код: Выделить всё

/**
* This class is used to load the CSV column names from the application.properties file.
* TODO: This is a temporary solution because @ConfigurationProperties does not work with immutable Map objects, which is a problem because the CSV column names should not be changed at runtime.
*/
@Getter
@Setter
@Component
@ConfigurationProperties(prefix = "app.csv")
public class CsvSchemas {
private Map schema = new HashMap();

public String[] getColumnNames(String schemaName) {
List schema = this.schema.get(schemaName);
if (schema == null) {
throw new IllegalArgumentException("Schema not found: " + schemaName);
}
return schema.toArray(String[]::new);
}
}
Что касается остального, я немного застрял, потому что не знаю точно, как адаптировать остальную часть кода:

TransactionFieldSetMapper.class:

Код: Выделить всё

@Component
public class TransactionFieldSetMapper extends BeanWrapperFieldSetMapper {

public TransactionFieldSetMapper() {
setTargetType(Transaction.class);

DefaultConversionService conversionService = new DefaultConversionService();
conversionService.addConverter(String.class, LocalDate.class, source -> LocalDate.parse(source, DateTimeFormatter.ISO_LOCAL_DATE));

setConversionService(conversionService);
}

}

Код: Выделить всё

@Component
public class TransactionItemProcessor implements ItemProcessor {
@Override
public @Nullable Transaction process(Transaction transaction) {
// No transformation needed for the moment
return transaction;
}
}
Транзакции автоматически сохраняются в базе данных MySQL. У меня также есть класс для постобработки, так как мне нужно выполнить несколько запросов после задания:

CategorizationPostProcessing.java:

Код: Выделить всё

@Log4j2
@Component
public class CategorizationPostProcessing implements JobExecutionListener {

@Autowired
private ObjectMapper objectMapper;

@Autowired
private TransactionRepository transactionRepository;

@Override
public void beforeJob(JobExecution jobExecution) {
// no-op
}

@Override
public void afterJob(JobExecution jobExecution) {
log.info("Job ended with status: {}", jobExecution.getStatus());

(...)
}

}
Мой вопрос
Является ли это стандартным способом обработки динамических форматов CSV в Spring Batch 6?
Для меня важно то, что я не хочу менять код Java в случае, если я захочу поддерживать другой банковский формат CSV.
Я старший разработчик Java/Spring, но честно пытаюсь понять, как это реализовать чисто. Я постараюсь легко объяснить, какие есть варианты, насколько я понимаю:
  • Сопоставьте имена столбцов с FinalTransaction без каких-либо знаний о SchemaType . Хорошо, но не идеально?
  • Получаем тип схемы в качестве входных данных (что я делаю) и выбираем Reader. Плохо, я не хочу писать Java-код каждый раз, когда хочу поддержать новый банк.
  • Что еще??
Примеры кода помогают, спасибо, ребята :)

Подробнее здесь: https://stackoverflow.com/questions/798 ... -entity-wi
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «MySql»