Мой валидатор не работает, когда userRepositary пытается сохранить нового пользователя в базе данных - PullRequest
1 голос
/ 07 июля 2019

Я пытаюсь создать свою аннотацию проверки.

Когда проверка не проходит, это хорошо работает. Я получаю сообщение о. Но когда проверка проходит успешно, я получаю RollbackException.

Что я делаю в моей аннотации валидации?

Я хочу проверить уникальный адрес электронной почты в таблице пользователей. Поэтому я создал @annotation:

package ru.project.domain.validation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import javax.validation.Constraint;
import javax.validation.Payload;

@Constraint(validatedBy = UniqueEmailValidator.class)
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface UniqueEmail {

    public String message() default "e-mail exist!";

    public Class<?>[] groups() default {};

    public Class<? extends Payload>[] payload() default{};

}

Я создал Validator:

package ru.project.domain.validation;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

import org.springframework.beans.factory.annotation.Autowired;

import ru.project.service.UserService;

public class UniqueEmailValidator implements ConstraintValidator<UniqueEmail, String> {

    @Autowired
    private UserService userService;

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        return value != null && !userService.isEmailAlredyUse(value);
    }

}

Когда я ввожу неуникальное письмо, я получаю сообщение «электронная почта существует!»

Но когда я ввожу уникальный адрес электронной почты, я получаю сообщение об ошибке:

2019-07-07 13: 14: 09.770 ОШИБКА 11680 --- [io-8080-exec-10] o.h.i.ExceptionMapperStandardImpl: HHH000346: ошибка во время управляемая очистка [HV000028: непредвиденное исключение во время вызова isValid.] 2019-07-07 13: 14: 09.777 ОШИБКА 11680 --- [io-8080-exec-10] o.a.c.c.C. [. [. [/]. [dispatcherServlet]: Servlet.service () для сервлет [dispatcherServlet] в контексте с путем [] вызвал исключение [Ошибка обработки запроса; вложенное исключение org.springframework.transaction.TransactionSystemException: не удалось совершить JPA транзакцию; вложенное исключение javax.persistence.RollbackException: ошибка при фиксации транзакция] с первопричиной

java.lang.NullPointerException: null at ru.project.domain.validation.UniqueEmailValidator.isValid (UniqueEmailValidator.java:17) ~ [классы /: нет] в ru.project.domain.validation.UniqueEmailValidator.isValid (UniqueEmailValidator.java:1) ~ [классы /: нет] в org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.validateSingleConstraint (ConstraintTree.java:171) ~ [hibernate-validator-6.0.17.Final.jar: 6.0.17.Final] в org.hibernate.validator.internal.engine.constraintvalidation.SimpleConstraintTree.validateConstraints (SimpleConstraintTree.java:68) ~ [hibernate-validator-6.0.17.Final.jar: 6.0.17.Final] в org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.validateConstraints (ConstraintTree.java:73) ...

Функция isValid вызывается дважды. При проверке после нажатия кнопки в форме и при попытке в пользовательском репозитории попытаться сохранить нового пользователя.

Я покажу, что мне каждый раз показывает отладчик.

При нажатии кнопки на форме (уникальный адрес электронной почты): enter image description here

Когда userRepository пытается сохранить нового пользователя: enter image description here

ОБНОВЛЕНИЕ: isEmailAlreadyUse:

public boolean isEmailAlredyUse(String value) {
        User user = userRepository.findByEmail(value);
        if(user != null) {
            return true;
        }
        return false;
    }

Во время второго запуска userService = null: enter image description here

Ответы [ 2 ]

0 голосов
/ 08 июля 2019

Одним из решений является отключение проверки, когда «спящий режим» сохраняет объект в базе данных.Для этого вам нужно установить следующее свойство в вашем application.properties

spring.jpa.properties.javax.persistence.validation.mode = none

0 голосов
/ 07 июля 2019

Попробуйте это:

ExtendedEmailValidator.java:

@Email(message="Please provide a valid email address")
@Pattern(regexp=".+@.+\\..+", message="Please provide a valid email address")
@Target( { ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = {})
@Documented
public @interface ExtendedEmailValidator {
    String message() default "Please provide a valid email address";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

Как это использовать? В вашей сущности добавить это:

    @Column
    @ExtendedEmailValidator(message = "custom message")
    private String email;

в вашем @Controller попробуйте это:

@PostMapping
public ModelAndView createNewUser(@Valid @ModelAttribute("user") User user, BindingResult bindingResult) {
ModelAndView modelAndView = new ModelAndView();
User userExists = userService.findUserByEmail(user.getEmail());

if (userExists != null) {
  bindingResult
               .rejectValue("email", "error.user",
                            "There is already a user registered with the email provided");
}

if(bindingResult.hasErrors()){
    modelAndView.setViewName("registration");
    return modelAndView;
}

/*
Other code
*/
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...