Как я могу программно вызвать тот же валидатор, который работает в методе @RequestMethod с параметром @Valid в Spring?

У меня есть класс с аннотацией проверки спящего режима в некоторых полях (например, @NotNull и @Size(min = 4, max = 50) и т. д.)

public class MyClass {

    Long id;

    @NotEmpty
    @Size(min = 4, max = 50)
    String machineName;

    @NotEmpty
    @Size(min = 4, max = 50)
    String humanName;

    // Getters, setters, etc…
}

У меня также есть собственный контроллер, который действует как JSON API, и десериализатор JSON, который создает объекты MyClass при вызове методов API. В моем пользовательском контроллере у меня есть метод для создания нового объекта этого типа:

@RequestMapping(method = RequestMethod.POST)
public long createMyObject(@RequestBody @Valid MyClass newObj) {
    // Create the object in the database
    return newObj.getId();
}

и еще один метод, который обновляет существующий объект

@RequestMapping(method = RequestMethod.PUT)
public void updateMyObject(@RequestBody MyClass updatedObj) {
    MyClass existingObj = // Get existing obj from DB by updatedObj.getId();

    // Do some secondary validation, such as making sure that a specific
    // field remains unchanged compared to the existing instance
    if (existingObj.getMachineName() != null && 
            !existingObj.getMachineName().equals(updatedObj.getMachineName())) {
        throw new CannotChangeMachineNameException();
    }
    else {
        updatedObj.setMachineName(existingObj.getMachineName());
    }

    // [HERE IS WHERE I WANT THE MAGIC TO HAPPEN]

    // Save updatedObj to the database
}

Хотя я могу использовать @Valid в createMyObject, я не могу использовать его в updateMyObject, потому что наша реализация API требует, чтобы имя_машины оставалось неизменным — пользователи могут вызывать API с объектом JSON, который либо полностью исключает имя_машины, либо заполняет его тем же значением, которое существует в базе данных. .*

Перед сохранением обновленного объекта в базе данных я хочу вызвать тот же валидатор, который вызовет аннотацию @Valid. Как я могу найти этот валидатор и использовать его?


person Daniel    schedule 04.07.2013    source источник
comment
Я думаю, вы можете использовать группы проверки. Все проверки, кроме @NotNull на machineName (или пользовательского валидатора, который сравнивает старое и новое имя), должны быть в группе по умолчанию, а оставшийся валидатор должен быть в группе Update. Используйте обе группы в методе updateMyObject. См. docs.jboss.org /hibernate/validator/5.0/reference/en-US/html/   -  person Eric Jablow    schedule 04.07.2013


Ответы (1)


Ничто не говорит о том, что вам нужно использовать @Valid только в методах вашего контроллера. Почему бы не создать метод проверки, который принимает параметр, который вы аннотируете как @Valid, а затем просто возвращает тот же параметр.

Как это:

public Book validateBook(@Valid Book book) {
   return book;
}

Похоже, альтернативой было бы использование пакета проверки Hibernate. Вот документация.

По сути, вы получаете Validator из ValidationFactory, а затем используете валидатор следующим образом:

 @Test
    public void manufacturerIsNull() {
        Car car = new Car(null, "DD-AB-123", 4);

        Set<ConstraintViolation<Car>> constraintViolations =
            validator.validate(car);

        assertEquals(1, constraintViolations.size());
        assertEquals("may not be null", constraintViolations.iterator().next().getMessage());
}
person CorayThan    schedule 04.07.2013
comment
Спасибо! Это привело меня достаточно близко к ответу - первый метод не сработал, я сделал что-то похожее на второй метод: Set‹ConstraintViolation‹MyClass›› errors = Validation.buildDefaultValidatorFactory().getValidator().validate(updatedObj); // Я понял это из документации, которую вы указали - person Daniel; 04.07.2013
comment
вызывает ли метод validateBook какие-либо исключения? что делать, если проверка не удалась? - person Alexandros Kourtis; 30.08.2020
comment
первый метод не инициирует никакой проверки. или я что-то упускаю? - person Happy; 30.09.2020
comment
@Happy Скорее всего, вы вызываете метод из того же класса, поэтому метод проверки не передается через прокси. - person Dmitry Senkovich; 29.01.2021