Я сталкивался с той же проблемой несколько месяцев назад. Вместо автоматического подключения хранилища передайте службу, которая уже использует тот же хранилище, через аннотацию.
Объявите аннотацию для принятия поля, которое должно быть уникальным, и службы, выполняющей проверку.
@Target({ ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = UniqueUsernameValidator.class)
@Documented
public @interface UniqueUsername {
String message() default "{com.domain.user.nonUniqueUsername}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
Class<? extends UniqueUsernameValidation> service(); // Validating service
String fieldName(); // Unique field
}
Используйте его на POJO, как:
@NotBlank
@Size(min = 2, max = 30)
@UniqueUsername(service = UserService.class, fieldName = "username")
private String username;
Обратите внимание, что служба, переданная в аннотацию (Class<? extends UniqueUsernameValidation> service()
), должна реализовывать интерфейс UniqueUsernameValidation
.
public interface UniqueUsernameValidation {
public boolean isUnique(Object value, String fieldName) throws Exception;
}
Теперь заставьте переданный UserService
реализовать интерфейс выше и переопределить его единственный метод:
@Override
public boolean isUnique(Object value, String fieldName) throws Exception {
if (!fieldName.equals("username")) {
throw new Exception("Field name not supported");
}
String username = value.toString();
// Here is the logic: Use 'username' to find another username in Repository
}
Не забудьте UniqueUsernameValidator
, который обрабатывает аннотацию:
public class UniqueUsernameValidator implements ConstraintValidator<UniqueUsername, Object>
{
@Autowired
private ApplicationContext applicationContext;
private UniqueUsernameValidation service;
private String fieldName;
@Override
public void initialize(UniqueUsername unique) {
Class<? extends UniqueUsernameValidation> clazz = unique.service();
this.fieldName = unique.fieldName();
try {
this.service = this.applicationContext.getBean(clazz);
} catch(Exception ex) {
// Cant't initialize service which extends UniqueUsernameValidator
}
}
@Override
public boolean isValid(Object o, ConstraintValidatorContext context) {
if (this.service !=null) {
// here you check whether the username is unique using UserRepository
return this.service.isUnique(o, this.fieldName))
}
return false;
}
}