当前位置: 首页 > 知识库问答 >
问题:

javax.validation.验证异常: HV000064:无法实例化ConstraintValidator

尹英华
2023-03-14

我跟随这篇博文,尝试实现一个自定义验证器来验证复合主键约束,但失败了:

javax.validation.ValidationException: HV000064: Unable to instantiate ConstraintValidator: com.directory.domain.model.validators.StorePoolValidator.
    at com.directory.domain.repositories.StorePoolRepositoryTest.shouldReturnPoolByStore(StorePoolRepositoryTest.java:30)
Caused by: java.lang.NoSuchMethodException: com.directory.domain.model.validators.StorePoolValidator.<init>()
    at com.directory.domain.repositories.StorePoolRepositoryTest.shouldReturnPoolByStore(StorePoolRepositoryTest.java:30)

以下是验证器注释界面的代码:

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

@Retention(RUNTIME)
@Target({FIELD})
@Constraint(validatedBy = StorePoolValidator.class)
public @interface UniqueStorePoolConstraint {
    String message() default "Store pool validation failed";

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

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

下面是validator类:

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.List;

public class StorePoolValidator implements ConstraintValidator<UniqueStorePoolConstraint, StorePoolId> {

    private StorePoolRepository storePoolRepository;

    public StorePoolValidator(StorePoolRepository storePoolRepository) {
        this.storePoolRepository = storePoolRepository;
    }

    @Override
    public void initialize(UniqueStorePoolConstraint constraintAnnotation) {

    }

    @Override
    public boolean isValid(StorePoolId id, ConstraintValidatorContext context) {
        final List<StorePool> storePools = storePoolRepository.findAllByStoreNumber(id.getThirdNumber());

        return storePools.isEmpty();
    }
}

以下是实体类:

@Entity
@Getter
@Setter
@Builder
@AllArgsConstructor
@Table(name = "STORE_POOLS")
public class StorePool implements Serializable {

    public StorePool() {
    }

    @EmbeddedId
    @UniqueStorePoolConstraint
    private StorePoolId id;
}

及其主键类:

import javax.persistence.Column;
import javax.persistence.Embeddable;
import javax.validation.constraints.NotNull;
import java.io.Serializable;

@Getter
@Setter
@Builder
@ToString
@Embeddable
@EqualsAndHashCode
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class StorePoolId implements Serializable {

    @Column(name = "pool", nullable = false)
    @NotNull
    private Integer pool;

    @Column(name = "third_number", nullable = false)
    @NotNull
    private Integer thirdNumber;
}

我尝试运行以下测试:

@RunWith(SpringRunner.class)
@DataJpaTest
public class StorePoolRepositoryTest {

    @Autowired
    private StorePoolRepository storePoolRepository;

    @Autowired
    private TestEntityManager entityManager;

    @Test
    public void shouldReturnPoolByStore() {
        final StorePool storePool = StorePoolBuilder.buildStorePool(1, 1);
        entityManager.persist(storePool);
        entityManager.flush();

        final List<StorePool> storePools = storePoolRepository.findAllByStoreNumber(1);

        assertThat(storePools).containsExactly(storePool);
    }
}

我错过了什么?谢谢您。

共有3个答案

柯子琪
2023-03-14

我基本上面临着同样的问题,但通过模拟测试,我解决了这个问题:

>

接口:

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

 String message() default "This username is in use";

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

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

}

实施:

 @RequiredArgsConstructor
 public class UniqueUsernameValidator implements ConstraintValidator<UniqueUsername, String> {

     private final UserRepository repository;

     @Override
     public boolean isValid(String username, ConstraintValidatorContext constraintValidatorContext) {
         return !repository.existsById(username);
     }
}

@SpringBootTest

通过Spring配置设置MockMvc:

@ExtendWith(MockitoExtension.class)
@SpringBootTest
public class RegistrationTest {

    @Autowired
    private WebApplicationContext wac;

    private MockMvc mockMvc;

    @BeforeEach
    void setUp() {
        this.mockMvc = MockMvcBuilders
                .webAppContextSetup(wac)
                .alwaysDo(print())
                .build();
    }

    // your tests

}
万俟超
2023-03-14

默认情况下需要添加一个构造函数空StorePoolValidator以便初始化验证器。

public StorePoolValidator() {
}

更新

为了使用存储库,可以将验证器添加为服务。那么答案是:

@Service
public class StorePoolValidator implements ConstraintValidator<UniqueStorePoolConstraint, StorePoolId> {

    @Autowired
    private StorePoolRepository storePoolRepository;

    @Override
    public void initialize(UniqueStorePoolConstraint constraintAnnotation) {

    }

    @Override
    public boolean isValid(StorePoolId id, ConstraintValidatorContext context) {
        final List<StorePool> storePools = storePoolRepository.findAllByStoreNumber(id.getThirdNumber());

        return storePools.isEmpty();
    }
}
单于楚
2023-03-14

抱歉讨论迟到了。

首先,创建一个ContextProvider,它是您需要的bean的提供者。

@Component
public class ContextProvider implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        ContextProvider.applicationContext = applicationContext;
    }

    public static Object getBean(Class cls) {
        return ContextProvider.applicationContext.getBean(cls);
    }

}

现在你可以这样做:

ContextProvider.getBean(StorePoolRepository.class);

这解决了NPE,您可以使用任何组件进行验证。

在你的情况下StorePoolValidator,

@Service
public class StorePoolValidator implements ConstraintValidator<UniqueStorePoolConstraint, StorePoolId> {

    private StorePoolRepository storePoolRepository;

    @Override
    public void initialize(UniqueStorePoolConstraint constraintAnnotation) {
         this.storePoolRepository = (StorePoolRepository) ContextProvider.getBean(StorePoolRepository.class) 
    }

    @Override
    public boolean isValid(StorePoolId id, ConstraintValidatorContext context) {
        final List<StorePool> storePools = storePoolRepository.findAllByStoreNumber(id.getThirdNumber());

        return storePools.isEmpty();
    }
}

就这样。

 类似资料:
  • 最近我更新了我的Hibernate从3.1到4.3,我正在尝试使用注释而不是xml。使用Xml,一切都运行良好,注释会抛出一堆异常。最后一个我被卡住的是下面的堆栈痕迹,请给它一些启示。我非常需要帮助,因为堆栈跟踪没有给我任何特定的工作区域。我使用的是Hibernate 4.3 java辅助3.18 我试着使用javaassistjar,这是每个人都建议的,但是din;我帮不了我。然而,我有我的疑问

  • 我正在测试带注释的javax验证。它们在应用程序中工作良好,方法参数上有注释。但是当我试图通过手动构建验证工厂来测试它们时 我得到以下错误。 javax。验证。ValidationException:HV000183:无法初始化“javax”。艾尔。“表达工厂”。检查类路径上是否有EL依赖项,或者改用ParameterMessageInterpolator 收到这个错误后,我在gradle文件中添

  • 问题内容: 有没有一种方法可以使用javax.validation来验证类型为color的字符串类型的变量,该变量只需要使用注释就具​​有这些值(红色,蓝色,绿色,粉红色)? 我见过 ,但是有这样的事情吗 或多或少类似于在使用 问题答案: 在那种情况下,我认为使用@Pattern注释会更简单,如下面的代码片段所示。如果需要不区分大小写的评估,只需添加适当的标志:

  • 问题内容: 我正在尝试使用jena库为语义Web编写Java Web搜寻器。我有使用Netbeans构建项目。我收到两个错误: 无法实例化SLF4J LoggerFactory报告的异常:java.lang.NoClassDefFoundError:org / apache / log4j / Level 无法在org.slf4j.LoggerFactory.bind(LoggerFactory.

  • 我正在尝试使用jena库为语义网编写java web爬虫程序。我已经使用Netbeans构建了一个项目。我收到两个错误: > 未能实例化SLF4J LoggerFactory报告的异常:java。lang.NoClassDefFoundError:org/apache/log4j/Level 无法初始化类com。惠普。hpl。耶拿。rdf。模型impl。modelorg。slf4j。伐木厂。绑定(

  • 我有一个以下类: 当我尝试转换JSON时 对于这个类实例,我得到以下异常: 获取原因:com . faster XML . Jackson . databind . jsonmappingexception:无法构造com . medianet . rtb . mogli . commons . dto . ad exchange . floor price data的实例:没有字符串参数构造函数