Я не совсем уверен, что это хорошее дизайнерское решение, чтобы заставить валидаторы проверять команды на основе состояния базы данных. Например, если мне нужно проверить bean-компонент пользователя, помимо проверки того, что адрес электронной почты и имя пользователя пусты и т. д., мне также нужно отклонить значения, если они уже используются. Должна ли такая логика быть в валидаторах или сервисных объектах?
Должны ли валидаторы весной обращаться к базе данных?
Ответы (6)
Что ж, ваши валидаторы — это просто Spring Bean-компоненты, так что их можно внедрять вместе с сервисными объектами, которые обрабатывают доступ к данным. Вы можете заставить своих валидаторов получать данные из базы данных без ущерба для дизайна.
Это во многом будет зависеть от того, как вы определяете валидацию. Подумайте вот о чем: вы что-то покупаете и вводите номер своей кредитной карты. Если контрольная цифра не совпадает, вы не прошли проверку. Транзакция не предпринималась. Однако, если это действительный номер кредитной карты, но он не соответствует вашему почтовому индексу (требуется взаимодействие с БД или третьей стороной), то это ошибка платежа.
Теперь подумайте вот о чем: вы вводите свой адрес и вводите Mastiffica в качестве своей страны. Почему система вообще позволила вам ввести это - они должны были ограничить интерфейс только допустимыми записями (в БД не требуется пост-запись).
Или введите «пятьдесят» в поле суммы на экране банковского платежа. Почему он разрешает туда буквы - это не проходит проверку (нет необходимости в БД). Но затем вы вводите 50 в поле суммы, и оказывается, что на вашем счету нет пятидесяти фунтов. Это ошибка проверки? Или это неудачная транзакция?
Теперь предположим, что вы прошли все основные проверки ввода (контрольная сумма кредитной карты, страна, цифры, почтовый индекс), и транзакция не удалась, поскольку срок действия вашей кредитной карты истек. Это ошибка проверки или неудачная транзакция?
Вы можете рассматривать проверку как базовую гарантию того, что пользователи не будут вводить совершенно необоснованные данные, или вы можете думать о проверке как «Я могу завершить эту транзакцию с данными, которые мне предоставили». Лично я бы предпочел первое, но опять же, это вопрос определения.
Затем есть аспект проверки первой строки в качестве меры безопасности - дикие данные, которые были приняты за ваш верхний уровень пользовательского интерфейса, могут представлять угрозу безопасности (например, SQL-инъекция)
нет, ИМХО валидаторы должны быть небольшими и без побочных эффектов, чтобы их можно было использовать. легко комбинироваться. Безусловно, валидатор должен быть отделен от уровня постоянства.
Я проверил один из своих и вызываю сервисный уровень из валидатора:
@Service
public final class StartFormValidator {
private FacilityService facilityService;
private AdminService adminService;
/**
* Verify that they've selected a facility. Verify that they've selected a
* valid facility. Verify that they've selected a view and that it's a valid
* view.
*
* @param startForm
* @param errors
* @return true if no errors were set
*/
public boolean isValid(final StartForm startForm, final Errors errors) {
if (startForm.getFacilityId() == 0) {
errors.rejectValue("facilityId", "facilityIdEmpty",
"Select a facility.");
}
if (!this.facilityService.isFacilWaitlistEnabled(startForm
.getFacilityId())) {
errors.rejectValue("facilityId", "facilityInvalid",
"Invalid facility");
}
if (StringUtils.isBlank(startForm.getPassword())) {
errors.rejectValue("password", "passwordEmpty",
"Enter the password.");
return (false);
}
if (!this.adminService.validateAdmin(startForm.getPassword()))
errors.rejectValue("password", "passwordInvalid",
"Incorrect password");
return (!errors.hasErrors());
}
/**
* @param _facilityService
*/
@Autowired
public void setFacilityService(final FacilityService _facilityService) {
this.facilityService = _facilityService;
}
/**
* @param _adminService
*/
@Autowired
public void setAdminService(final AdminService _adminService) {
this.adminService = _adminService;
}
}
Если вы действительно верите в "MVC", то я так не думаю, что вы хотели бы, чтобы ваши валидаторы обращались к базе данных. Проверка - это этап, который по существу проверяет данные с точки зрения бизнес-логики.
Базе данных не нужно знать, как ее будут использовать валидаторы, и валидаторы не должны знать, что такое база данных. Это просто не вписывается в модель MVC. Завтра, если у вас есть данные, поступающие из нескольких источников, вы все равно пойдете вперед и сообщите своим валидаторам, к какому конкретному источнику он должен получить доступ и при каких условиях. Это само по себе будет составлять логику, которая даже не требуется. в приложении.
Тип проверки, которую вы ищете, будет рассматриваться как часть бизнес-объектов, что гарантирует, что еще до того, как объекты службы будут вызваны; такой комбинации еще не существует.
Сервисные объекты также не должны содержать бизнес-проверки, поэтому они не относятся ни к валидаторам, ни к сервисным объектам. Но да, если приложение достаточно маленькое, чтобы не беспокоиться о слишком большом количестве слоев, асимметричный подход хорош, но только до тех пор, пока «он соблюдается как стандарт во всем».
Короче говоря, я чувствую, что весенние валидаторы предназначены для базовых проверок, а не для бизнес-проверок.
я предпочитаю проверку, которая использует базу данных из-за удобства использования конечным пользователем.
При отправке регистрационной формы вы хотите проверить, является ли имя пользователя синтаксически правильным и не задано ли это имя пользователя (требуется доступ к БД).
Форма может вернуться со всеми ошибками сразу. Он может показать пользователю все проблемы. Пользователь может исправить это и снова отправить форму.
Я знаю, что вы можете сделать это умнее с помощью ajax и т. Д., Это не главное.
Я всегда все проверяю. Я проверяю, будет ли эта форма обрабатываться предстоящей транзакцией. Если нет, я получаю исключение из-за некоторого одновременного доступа, который можно легко обработать.