如何在 ConstraintValidator 中执行 @Entity 查询
How to perform an @Entity query inside a ConstraintValidator
场景是,在持久化 Log
实体 class 之前,应检查其 属性、String description
是否至少包含在 IllegalWord
实体class。下面是两个实体classes:
的映射
// 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
实体 class 执行 select *
,因此我为其创建了一个存储库 class:
// IllegalWordRepository.java
@Repository
public interface IllegalWordRepository extends CrudRepository<IllegalWord, Long> {}
然后创建 ConstraintValidator
验证器 class 将由 NotContainingIllegalWords
注释使用,反过来,将用于注释 String description
字段 Log
实体 class:
// 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
。
我假设我在存储库 class 中编码有问题,所以我尝试在带注释的 @Service
中使用 @Autowired private IllegalWordRepository illegalWordRepository
class 并且令人惊讶的是它被注入到那里正确(e.i。不是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
存储库 class 没有任何问题。只是它没有注入 NotContainingIllegalWordsValidator
验证器 class 中,因为我打算将它与 @Autowired
注释一起使用(如果这就是 @Autowired
注释的预期功能,对不起,我是 Spring Framework 的新手。)。
如果有关于如何在 ConstraintValidator
实例中执行 @Entity 查询的正确方法,请告诉我。
相关未回答的 SO 问题:Inject Repository inside ConstraintValidator with Spring 4 and message interpolation configuration
尝试失败:
我尝试用 @Configurable
注释对 NotContainingIllegalWordsValidator
class 进行注释,如下所示:
@Configurable(autowire=Autowire.BY_NAME, preConstruction=true)
public class NotContainingIllegalWordsValidator implements ConstraintValidator<NotContainingIllegalWords, Object> {
但 illegalWordRepository
属性 仍然是 null
。
来自我的 answer to a similar question:
@Autowired 在 ConstraintValidator 实现中正常工作的最小设置是将此 bean 放在 Spring @Configuration:
中
@Bean
public Validator defaultValidator() {
return new LocalValidatorFactoryBean();
}
这是demo项目
因为你的验证器没有被 Spring 初始化,你不能向它注入任何东西。您必须通过静态变量访问 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);
...
}
}
场景是,在持久化 Log
实体 class 之前,应检查其 属性、String description
是否至少包含在 IllegalWord
实体class。下面是两个实体classes:
// 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
实体 class 执行 select *
,因此我为其创建了一个存储库 class:
// IllegalWordRepository.java
@Repository
public interface IllegalWordRepository extends CrudRepository<IllegalWord, Long> {}
然后创建 ConstraintValidator
验证器 class 将由 NotContainingIllegalWords
注释使用,反过来,将用于注释 String description
字段 Log
实体 class:
// 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
。
我假设我在存储库 class 中编码有问题,所以我尝试在带注释的 @Service
中使用 @Autowired private IllegalWordRepository illegalWordRepository
class 并且令人惊讶的是它被注入到那里正确(e.i。不是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
存储库 class 没有任何问题。只是它没有注入 NotContainingIllegalWordsValidator
验证器 class 中,因为我打算将它与 @Autowired
注释一起使用(如果这就是 @Autowired
注释的预期功能,对不起,我是 Spring Framework 的新手。)。
如果有关于如何在 ConstraintValidator
实例中执行 @Entity 查询的正确方法,请告诉我。
相关未回答的 SO 问题:Inject Repository inside ConstraintValidator with Spring 4 and message interpolation configuration
尝试失败:
我尝试用 @Configurable
注释对 NotContainingIllegalWordsValidator
class 进行注释,如下所示:
@Configurable(autowire=Autowire.BY_NAME, preConstruction=true)
public class NotContainingIllegalWordsValidator implements ConstraintValidator<NotContainingIllegalWords, Object> {
但 illegalWordRepository
属性 仍然是 null
。
来自我的 answer to a similar question:
@Autowired 在 ConstraintValidator 实现中正常工作的最小设置是将此 bean 放在 Spring @Configuration:
中@Bean
public Validator defaultValidator() {
return new LocalValidatorFactoryBean();
}
这是demo项目
因为你的验证器没有被 Spring 初始化,你不能向它注入任何东西。您必须通过静态变量访问 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);
...
}
}