Spring MVC + Hibernate: стратегии проверки данных

мы все знаем, что Spring MVC хорошо интегрируется с валидатором Hibernate и JSR-303 в целом. Но валидатор Hibernate, как кто-то сказал, предназначен только для проверки бобов, что означает, что более сложные проверки должны быть перенесены на уровень данных. Примеры таких проверок: уникальность бизнес-ключа, зависимость внутри записей (что обычно указывает на проблемы проектирования БД, но мы все живем в несовершенном мире). Даже простые проверки, такие как длина поля строки, могут управляется некоторым значением DB, что делает Hibernate Validator непригодным для использования.

Итак, мой вопрос в том, есть ли что-то Spring или Hibernate или JSR для выполнения таких сложных проверок? Есть некоторые создана шаблон или часть технологии для выполнения такой проверки в стандартной настройке контроллера-службы-репозитория на основе Spring и Hibernate?

обновление: позвольте мне быть более конкретным. Например, есть форма, которая отправляет AJAX save запрос к контроллеру save метод. Если происходит какая-то ошибка проверки-простая или "сложная" - мы должны вернуться в браузер с некоторым json, указывающим проблемное поле и связанную ошибку. Для простых ошибок я могу извлечь поле (если есть) и сообщение об ошибке из BindingResult. Какая инфраструктура (может быть, конкретные, а не специальные исключения?) вы бы предложили для "сложных" ошибок? Использование обработчика исключений не кажется мне хорошей идеей, потому что разделение одного процесса проверка между save способ и @ExceptionHandler делает вещи сложные. В настоящее время я использую некоторые специальные исключения (например, ValidationException):

public @ResponseBody Result save(@Valid Entity entity, BindingResult errors) {
    Result r = new Result();
    if (errors.hasErrors()) {
        r.setStatus(Result.VALIDATION_ERROR);     
        // ...   
    } else {
        try {
            dao.save(entity);
            r.setStatus(Result.SUCCESS);
        } except (ValidationException e) {
            r.setStatus(Result.VALIDATION_ERROR);
            r.setText(e.getMessage());
        }
    }
    return r;
}

можете ли вы предложить более оптимальный подход?

1 ответов


Да, есть старый добрый установленный шаблон Java исключений.
Spring MVC интегрирует его довольно хорошо (для примеров кода Вы можете сразу перейти ко второй части моего ответа).

то, что вы называете "сложными проверками", на самом деле является исключениями : ошибка уничности бизнес-ключа, ошибки низкого уровня или БД и т. д.


напоминание: что такое проверка весной MVC ?

проверка должна произойти на уровень представления. Это в основном о проверке представленных полей формы.

мы могли бы классифицировать их на два вида :

1) Свет проверки (с проверкой JSR-303/Hibernate): проверка того, что отправленное поле имеет заданное @Size/@Length, что это @NotNull или @NotEmpty/@NotBlank, проверяя, что у него есть и т. д.

2) тяжелая проверка, или сложная проверка больше о частных случаях проверки полей, такие как перекрестная проверка полей:

  • Пример 1: форма имеет fieldA, fieldB и fieldC. По отдельности каждое поле может быть пустым, но по крайней мере одно из них не должно быть пустым.
  • Пример 2: if userAge поле имеет значение ниже 18,responsibleUser поле не должно быть null и responsibleUserвозраст должен быть старше 21 года.

эти проверки могут быть реализованы с реализации весеннего валидатора, или пользовательские Примечания/ограничения.

теперь я понимаю, что со всеми этими средствами проверки, плюс тот факт, что весна не навязчива вообще и позволяет вам делать все, что вы хотите (к лучшему или к худшему), можно соблазниться использовать "молоток проверки" для чего-либо смутно связанного с обработкой ошибок.
И это сработает : только с проверкой вы проверяете каждую возможную проблему в своих валидаторах / аннотациях (и вряд ли бросаете какое-либо исключение в Нижнем отводков.) Это плохо, потому что вы молитесь, чтобы вы подумали обо всех случаях. Вы не используете исключения Java, которые позволили бы вам упростить вашу логику и уменьшить вероятность ошибки, забыв проверить, что что-то имело ошибку.

поэтому в весеннем мире MVC не следует ошибаться в проверке (то есть,проверка пользовательского интерфейса) для нижнего слоя исключения, например, есть исключения службы или исключения ДБ (ключевые уникальность, так далее.).


как обрабатывать исключения в Spring MVC удобным способом ?

некоторые люди думают: "о боже, так в моем контроллере мне пришлось бы проверять все возможные проверенные исключения один за другим и думать об ошибке сообщения для каждого из них ? НИ ЗА ЧТО !". Я один из этих людей. :-)

для большинства случаев просто используйте некоторый общий проверенный класс исключений, который будут расширять все ваши исключения. Затем просто обработайте его в своем контроллере Spring MVC с @ExceptionHandler и общее сообщение об ошибке.

пример кода :

public class MyAppTechnicalException extends Exception { ... }

и

@Controller
public class MyController {

    ...

    @RequestMapping(...)
    public void createMyObject(...) throws MyAppTechnicalException {
        ...
        someServiceThanCanThrowMyAppTechnicalException.create(...);
        ...
    }

    ...

    @ExceptionHandler(MyAppTechnicalException.class)
    public String handleMyAppTechnicalException(MyAppTechnicalException e, Model model) {

        // Compute your generic error message/code with e.
        // Or just use a generic error/code, in which case you can remove e from the parameters
        String genericErrorMessage = "Some technical exception has occured blah blah blah" ;

        // There are many other ways to pass an error to the view, but you get the idea
        model.addAttribute("myErrors", genericErrorMessage);

        return "myView";
    }

}

простой, быстрый, легкий и чистый !

для тех случаев, когда вам нужно отображать сообщения об ошибках для некоторых конкретных исключений или когда вы не можете иметь общее исключение верхнего уровня из-за плохо разработанной устаревшей системы, которую вы не можете изменить, просто добавьте другие @ExceptionHandlers.
Еще один трюк: для менее загроможденного кода, вы можете обрабатывать несколько исключений с

@ExceptionHandler({MyException1.class, MyException2.class, ...})
public String yourMethod(Exception e, Model model) {
    ...
}

итог : когда использовать проверку ? когда использовать исключения ?

  • ошибки из UI = validation = средства проверки (JSR-303 аннотации, пользовательские аннотации, Spring validator)
  • ошибки из нижних слоев = исключения

когда я говорю "ошибки из пользовательского интерфейса", я имею в виду"пользователь ввел что-то не так в своей форме".

ссылки :