java - 如何在 ConstraintValidator 中执行 @Entity 查询

标签 java spring-boot spring-data-jpa hibernate-validator

场景是在持久化一个Log实体类之前,应该检查它的属性String description是否至少包含一个在IllegalWord中找到的词 实体类。下面是两个实体类的映射:

// Log.java
@Entity
public class Log {
    @GeneratedValue(strategy=GenerationType.SEQUENCE)
    @Id
    private Long id;

    @NotContainingIllegalWords
    private String description;
}

// IllegalWord.java
@Entity
public class IllegalWord {
    @GeneratedValue(strategy=GenerationType.SEQUENCE)
    @Id
    private Long id;
    private String word;
}

因为我将对 IllegalWord 实体类执行 select *,所以我为它创建了一个存储库类:

// IllegalWordRepository.java
@Repository
public interface IllegalWordRepository extends CrudRepository<IllegalWord, Long> {}

然后创建 ConstraintValidator validator 类,该类将由 NotContainingIllegalWords 注释使用,反过来,该类将用于注释 String description Log 实体类的字段:

// NotContainingIllegalWordsValidator.java
public class NotContainingIllegalWordsValidator implements ConstraintValidator<NotContainingIllegalWords, Object> {
    private static final Logger log = LoggerFactory.getLogger(NotContainingIllegalWordsValidator.class);

    @Autowired
    private IllegalWordRepository illegalWordRepository;
    
    public void initialize(NotContainingIllegalWords constraintAnnotation) {}

    public boolean isValid(String value, ConstraintValidatorContext cxt) {
        log.debug("illegalWordRepository is null? " + (illegalWordRepository == null));
        // Returns "illegalWordRepository is null? true"
        // It is not injected even with the @Autowired annotation.

        boolean valid = true;
        
        Collection<IllegalWord> illegalWords = illegalWordRepository.findAll();
        // Encounters a NullPointerException here.
        
        // valid = ...loop through illegalWords collection and match regex (or whatever optimal approach)
        // with @param value to check if it contains the illegal word.
        
        return valid;
    }

我认为它会像那样直截了当。但是语句 illegalWordRepository.findAll() 会抛出错误,因为 illegalWordRepository 变量为空。请注意,我试图在前面的语句中检查它是否为 null

我假设我在存储库类中编码有问题,所以我尝试在 @Service 注释类中使用 @Autowired private IllegalWordRepository illegalWordRepository 并且令人惊讶的是它被注入(inject)那里正确(即不是 null):

// IllegalWordService.java
@Service
public class IllegalWordService {
    private static final Logger log = LoggerFactory.getLogger(IllegalWordService.class);
    
    @Autowired
    private IllegalWordRepository illegalWordRepository;

    public IllegalWord generate(String word) {
        log.debug("illegalWordRepository is null? " + (illegalWordRepository == null));
        // Returns "illegalWordRepository is null? false"
        
        IllegalWord illegalWord = new IllegalWord();
        illegalWord.setWord(word);
        
        illegalWordRepository.save(illegalWord);
        // Didn't encounter a NullPointerException here.

        return illegalWord;
    }
}

因此,我想 IllegalWordRepository 存储库类没有任何问题。只是它没有注入(inject) NotContainingIllegalWordsValidator validator 类,因为我希望它与 @Autowired 注释一起使用(如果那是 @Autowired注释本来是为了起作用,很抱歉我是 Spring Framework 的新手。)。

如果有关于如何在 ConstraintValidator 实例中执行 @Entity 查询的正确方法,请告诉我。

相关未回答的 SO 问题:Inject Repository inside ConstraintValidator with Spring 4 and message interpolation configuration


尝试失败:

我尝试使用 @Configurable 注释来注释 NotContainingIllegalWordsValidator 类,如下所示:

@Configurable(autowire=Autowire.BY_NAME, preConstruction=true)
public class NotContainingIllegalWordsValidator implements ConstraintValidator<NotContainingIllegalWords, Object> {

但是 illegalWordRepository 属性仍然是 null

最佳答案

因为你的 validator 不是由 Spring 初始化的,你不能向它注入(inject)任何东西。您必须通过静态变量访问 ApplicationContext

@SpringBootApplication
public class MyApplication {

  private static ApplicationContext applicationContext;

  public static void main(final String[] args) {
    applicationContext = SpringApplication.run(MyApplication.class, args);
  }
  public static ApplicationContext getApplicationContext() {
    return applicationContext;
  }
}

在你的ConstraintValidator中:

public class NotContainingIllegalWordsValidator implements ConstraintValidator<NotContainingIllegalWords, Object> {
  public boolean isValid(String value, ConstraintValidatorContext cxt) {
    ApplicationContext applicationContext = MyApplication.getApplicationContext();
    IllegalWordRepository illegalWordRepository = applicationContext.getBean(IllegalWordRepository.class);
    ...
  }
}

关于java - 如何在 ConstraintValidator 中执行 @Entity 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63269723/

相关文章:

java - 如何在 REST assured 中调用 put 方法

使用自定义 java 运行时镜像时发生 javax.net.ssl.SSLHandshakeException 但并非没有

java - Java Try/Catch block 的基准测试

java - 无法加载在 Docker 中运行的 Spring Boot 应用程序

java - JPA 软删除存储库 + 审核

java - 删除现有数据库并在 Hibernate 中重新创建架构

gradle - Spring Boot Gradle 插件 - 多模块 fat jar

java - Maven Spring Boot 无法实例化 SLF4J LoggerFactory 报告异常 :

java - 如何保存包含其他实体列表的 JPA/Spring Data 实体,而不必全部查找?

java - Spring Repository @Async Future<List<T>> 返回错误类型