Hibernate 自定义验证程序导致StackOverflowException

Hibernate 自定义验证程序导致StackOverflowException,hibernate,spring-boot,spring-data-jpa,spring-data,check-constraints,Hibernate,Spring Boot,Spring Data Jpa,Spring Data,Check Constraints,我想实现ConstraintsValidator,它在注册新用户之前验证电子邮件是否可用,使用spring的depandency injection@Autowired将JPA存储库插入验证器中进行数据库搜索 我更改了hibernate的验证器工厂,以便spring实例化验证器,这样我就可以使用@Autowired 一切正常,但这就像验证进入无限循环,导致stackoverflowexception 注意:当我使用RESTJPA存储库时,验证是自动完成的(我没有调用validator.valid

我想实现
ConstraintsValidator
,它在注册新用户之前验证电子邮件是否可用,使用spring的depandency injection
@Autowired
将JPA存储库插入验证器中进行数据库搜索

我更改了hibernate的验证器工厂,以便spring实例化验证器,这样我就可以使用
@Autowired

一切正常,但这就像验证进入无限循环,导致
stackoverflowexception

注意:当我使用RESTJPA存储库时,验证是自动完成的(我没有调用
validator.validate()

@Getter
@Setter
@Entity
@UniqueCompteEmail
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public abstract class Compte implements Serializable, UserDetails {

    private static final long serialVersionUID = -5230227676515387462L;

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    private Integer id;

    @NotBlank
    @NotNull
    @Column(unique = true)
    private String username;

    @NotNull
    @NotBlank
    @Size(min = 6)
    private String password;

    @Email
    @NotNull
    @NotBlank
    @Column(unique = true)
    private String email;

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return new HashSet<GrantedAuthority>();
    }

    @Override
    public String getPassword() {
        return this.password;
    }

    @Override
    public String getUsername() {
        return this.username;
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }

    public abstract CompteType getTypeCompte();

    public abstract void setTypeCompte(CompteType typeCompte);

    public static enum CompteType {
        ETUDIANT, ADMINISTRATEUR
    }
}

@Repository
public interface CompteRepository extends JpaRepository<Compte, Integer> {

    public Optional<Compte> findByUsername(String username);

    public Optional<Compte> findByEmail(String email);
}

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = UniqueCompteEmailValidator.class)
@Target({ ElementType.TYPE })
public @interface UniqueCompteEmail {

    String message() default "{com.mssmfactory.bacsimulator.uniquecompteemail.message}";

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

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

public class UniqueCompteEmailValidator implements ConstraintValidator<UniqueCompteEmail, Compte> {

    @Autowired
    private CompteRepository compteRepository;

    @Override
    public void initialize(UniqueCompteEmail constraintAnnotation) {
    }

    @Override
    public boolean isValid(Compte value, ConstraintValidatorContext context) {
        if (value != null) {
            Optional<Compte> compte = this.compteRepository.findByEmail(value.getEmail());

            return !compte.isPresent();
        } else
            return false;
    }
}

@Component
public class ValidatorAddingCustomizer implements HibernatePropertiesCustomizer {

    @Autowired
    private ValidatorFactory validatorFactory;

    public void customize(Map<String, Object> hibernateProperties) {
        if (validatorFactory != null) {
            hibernateProperties.put("javax.persistence.validation.factory", validatorFactory);
        }
    }
}
@Getter
@塞特
@实体
@独家电子邮件
@继承(策略=InheritanceType.SINGLE_表)
公共抽象类Compte实现了可序列化的UserDetails{
私有静态最终长serialVersionUID=-5230227676515387462L;
@身份证
@GeneratedValue(策略=GenerationType.SEQUENCE)
私有整数id;
@不空白
@NotNull
@列(唯一=真)
私有字符串用户名;
@NotNull
@不空白
@尺寸(最小=6)
私有字符串密码;
@电子邮件
@NotNull
@不空白
@列(唯一=真)
私人字符串电子邮件;
@凌驾
公共集合[]组()默认值{};

类因为您没有定义任何事件,所以将为所有事件调用验证器

这些活动包括(见):

  • 事件发生前
  • 后创建事件
  • 事件发生前
  • 余震
  • BeforeLinkSaveEvent
  • AfterLinkSaveEvent
  • 事件发生前
  • 后删除事件
因为您将从db获取验证方法,所以您被困在一个无限循环中

您只需要用一个对流名称对验证器进行注释

@组件(“beforeCreateCompteValidator”)
公共UniqueCompteEmailValidator实现验证程序{
}
以及删除其他注释

Spring识别这个验证器并连接到右钩子


有关更多信息,请参见

,因为您没有定义任何事件,因此将为所有事件调用验证器

这些活动包括(见):

  • 事件发生前
  • 后创建事件
  • 事件发生前
  • 余震
  • BeforeLinkSaveEvent
  • AfterLinkSaveEvent
  • 事件发生前
  • 后删除事件
因为您将从db获取验证方法,所以您被困在一个无限循环中

您只需要用一个对流名称对验证器进行注释

@组件(“beforeCreateCompteValidator”)
公共UniqueCompteEmailValidator实现验证程序{
}
以及删除其他注释

Spring识别这个验证器并连接到右钩子

有关更多信息,请参见

明确答案(y)明确答案(y)