@Transactional
@NonNull
@VisibleForTesting
ImportFileActivityOutput processDbOperation(@NonNull final ImportFileActivityInput input) {
if (input.dataAction().equals(OVERWRITE)) {
final var truncateQuery =
"TRUNCATE TABLE \"%s\".\"%s\" RESTART IDENTITY CASCADE".formatted(SCHEMA, input.tableName());
try {
jdbcTemplate.execute(truncateQuery);
} catch (DataAccessException e) {
throw new IllegalStateException("Error executing truncate", e);
}
log.atInfo().addKeyValue("tableName", input.tableName()).log("Truncated table successfully");
}
convertImportFile(input.file(), input.requiredColumns(), input.delimiter())
.toStream()
.forEach(batch -> {
final var allRowsEmpty = batch.stream()
.allMatch(row -> row.values().stream().allMatch(value -> value == null || value.isBlank()));
if (allRowsEmpty) {
log.atInfo().addKeyValue("tableName", input.tableName()).log("No data to add for table");
return;
}
final var columnNames = new ArrayList(batch.get(0).keySet());
final var formattedColumnNames =
columnNames.stream().map(col -> "\"" + col + "\"").collect(joining(", "));
final var queryPlaceholders =
columnNames.stream().map(col -> "?").collect(joining(", "));
final var primaryKeys =
Optional.ofNullable(input.primaryKeys()).orElse(emptyList());
final var conflictColumns =
primaryKeys.stream().map(pk -> "\"" + pk + "\"").collect(joining(", ", "(", ")"));
final var updateClause = columnNames.stream()
.filter(col -> !primaryKeys.contains(col))
.map(col -> "\"" + col + "\" = EXCLUDED.\"" + col + "\"")
.collect(joining(", "));
final var query =
switch (input.dataAction()) {
case ADD -> "INSERT INTO \"%s\".\"%s\" (%s) VALUES (%s) ON CONFLICT %s DO NOTHING"
.formatted(
SCHEMA,
input.tableName(),
formattedColumnNames,
queryPlaceholders,
conflictColumns);
case ADD_UPDATE -> """
INSERT INTO "%s"."%s" (%s) VALUES (%s) \
ON CONFLICT %s DO UPDATE SET %s"""
.formatted(
SCHEMA,
input.tableName(),
formattedColumnNames,
queryPlaceholders,
conflictColumns,
updateClause);
case OVERWRITE -> "INSERT INTO \"%s\".\"%s\" (%s) VALUES (%s)"
.formatted(SCHEMA, input.tableName(), formattedColumnNames, queryPlaceholders);
default -> throw new IllegalStateException("Invalid request type");
};
final var batchArgs = batch.stream()
.map(row -> columnNames.stream().map(row::get).toArray(Object[]::new))
.toList();
try {
jdbcTemplate.batchUpdate(query, batchArgs);
} catch (DataAccessException e) {
log.atError()
.addKeyValue("tableName", input.tableName())
.setCause(e)
.log("error during " + input.dataAction() + " operation");
throw new IllegalStateException("Error executing batch " + input.dataAction(), e);
}
});
log.atInfo().addKeyValue("tableName", input.tableName()).log("Completed " + input.dataAction() + " operation");
return new ImportFileActivityOutput(
input.automationId(),
ActivityStatus.SUCCESS,
input.dataAction() + " complete for table: " + input.tableName());
}
< /code>
Так я в настоящее время выполняю запросы. Я занимаюсь конкатенацией строки, которая приведет к атакам инъекций SQL, поэтому я использую @SuppressfBarnings («SecSQLisprjdbc»). Мой вопрос заключается в том, как мне нужно изменить мои запросы для использования подготовленных заявлений, чтобы предотвратить необходимость подавления предупреждений об инъекциях и вообще не беспокоиться о атаках инъекций. «Партия» - это список . Спасибо!
Подробнее здесь: https://stackoverflow.com/questions/795 ... njection-a