@Transactional //Spring transactional
void saveFile(ExcelFile file) {
//Each sheet have different kind of entities and it is an ordered insert and first insert is needed before the second set of inserts
for(each sheet in excel file) {
List<Entity> entityList = convertIntoEntities(sheet);
ValidationResult vr = validateEntities(entityList);
saveEntities(entityList);
}
ValidationResult validateEntities(List<Entity> entityList) {
validator.validate(entityList) // The new validation we need to do before
}
void saveEntities(List<Entity> entityList) {
dao.saveEntities(entityList);
}
Здесь список сущностей формируется после чтения файла Excel, и мы добавляем логику проверки файла Excel. Мы не можем просто проверить Excel самостоятельно, нам нужно прочитать существующие записи базы данных перед проверкой.
Теперь валидатор проверяет Excel, где нам нужно просмотреть существующие сущности (какой-либо другой таблицы) в базе данных (это не внешнее ограничение, есть некоторая бизнес-логика), и он создает список validationErrorMessages для каждой недопустимой сущности.
Структура класса проверки:
ValidationResult {
boolean isValid;
List<String> errorMessage;
}
Мне пришло в голову два решения
изменить подпись сохранения и отправить ValidationResult (или перенести его в другой класс). В этом случае нам нужно самостоятельно управлять откатом, поскольку @Transactional не выполняет откат, когда мы не генерируем исключение.
Бросьте InvalidInputFileException, у которого действительно есть validationResult. (Причина, по которой мы хотим сохранить ValidationResult, нам нужно сообщить пользователю об ошибке проверки).
Я поддерживаю этот подход, поскольку для несогласованных данных правильно генерировать исключение, а во-вторых, @Transactional будет работать нормально, и нам не нужно управлять транзакциями. Однако я раньше не встречал в коде переменную-член в классе Exception, и можно ли это сделать?
Я думал, что в случае ValidationFailure он бросает
class InvalidInputFileException extends RuntimeException {
ValidationResult vr;
}