当userRepositary尝试在数据库中保存新用户时,我的验证器失败

时间:2019-07-07 10:35:16

标签: spring hibernate spring-boot validation

我尝试创建我的验证批注。

当验证失败时,它会很好地工作。我收到一条消息。但是当验证通过时,我得到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{};

}

我已经创建了验证器:

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()   路径[]中的servlet [dispatcherServlet]抛出异常   [请求处理失败;嵌套异常为   org.springframework.transaction.TransactionSystemException:无法   进行JPA交易;嵌套异常为   javax.persistence.RollbackException:提交错误   交易]的根本原因

     

java.lang.NullPointerException:为null   ru.project.domain.validation.UniqueEmailValidator.isValid(UniqueEmailValidator.java:17)   〜[classes /:na]在   ru.project.domain.validation.UniqueEmailValidator.isValid(UniqueEmailValidator.java:1)   〜[classes /:na]在   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被调用两次。在表单上的按钮之后进行验证时,以及当userRepository尝试保存新用户时。

我将展示每次调试器向我显示的内容。

当表单上的按钮(唯一的电子邮件)时: 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 :(得分:0)

尝试一下:

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
*/
}

答案 1 :(得分:0)

一个决定是在“休眠”状态下将实体保存到数据库中时关闭检查。为此,您需要在application.properties

中设置下一个属性。
  

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