Spring Boot - пользовательское ограничение Hibernate не внедряет службу - PullRequest
0 голосов
/ 07 мая 2018

Я постараюсь игнорировать другие детали и укорочу:

@Entity
public class User
    @UniqueEmail
    @Column(unique = true)
    private String email;
}

@Component
public class UniqueEmailValidatior implements ConstraintValidator<UniqueEmail,String>, InitializingBean {

    @Autowired private UserService userService;

    @Override
    public void initialize(UniqueEmail constraintAnnotation) {

    }

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        if(userService == null) throw new IllegalStateException();
        if(value == null) return false;
        return !userService.isEmailExisted(value);
    }

}

Это будет работать, когда проверка выполняется весной (Spring MVC @Valid или вводит Validator с использованием @Autowire), все будет хорошо. Но как только я сохраню сущность, используя Spring Data JPA:

User save = userRepository.save(newUser);

Hibernate попытается создать новый UniqueEmailValidatior без внедрения bean-компонента UserService. Итак, как я могу заставить Hibernate использовать мой UniqueEmailValidatior компонент без его создания нового. Я мог бы отключить проверку гибернации, используя spring.jpa.properties.javax.persistence.validation.mode=none, но я надеюсь, что есть другой способ

Обновление: вот мой UserService:

   @Autowired private Validator validator;
   @Transactional
    public SimpleUserDTO newUser(UserRegisterDTO user) {
        validator.validate(user);
        System.out.println("This passes");
        User newUser = new User(user.getUsername(),
                passwordEncoder.encode(user.getPassword()),user.getEmail(),
                "USER",
                user.getAvatar());
        User save = userRepository.save(newUser);
        System.out.println("This won't pass");
        return ....
    }

Ответы [ 3 ]

0 голосов
/ 07 мая 2018

Чтобы добавить бобы Spring в ваш ConstraintValidator, вам нужен определенный ConstraintValidatorFactory, который должен быть передан при инициализации ValidatorFactory.

Что-то вроде:

ValidatorFactory validatorFactory = Validation.byDefaultProvider()
    .configure()
    .constraintValidatorFactory( new MySpringAwareConstraintValidatorFactory( mySpringContext ) )
    .build();

с MySpringAwareConstraintValidatorFactory является ConstraintValidatorFactory, который вводит бобы внутрь вашего ConstraintValidator.

Я подозреваю, что ValidatorFactory, используемый Spring Data, не внедряет валидаторы при их создании, что вызывает сожаление.

Полагаю, вы сможете это переопределить. Или, что еще лучше, вы должны открыть проблему для Spring Boot / Spring Data, чтобы они правильно внедрили ConstraintValidator s, поскольку второй раз подряд у нас возникает этот вопрос на SO.

0 голосов
/ 07 мая 2018

Я ожидаю, что Spring Boot подключит существующий валидатор к EntityManager, очевидно, это не так.

Вы можете использовать HibernatePropertiesCustomizer и добавить свойства к существующему EntityManagerFactoryBuilder и зарегистрировать Validator.

ПРИМЕЧАНИЕ: Я предполагаю, что вы используете Spring Boot 2.0

@Component
public class ValidatorAddingCustomizer implements HibernatePropertiesCustomizer {

    private final ObjectProvider<javax.validation.Validator> provider;

    public ValidatorAddingCustomizer(ObjectProvider<javax.validation.Validator> provider) {
        this.provider=provider;
    }

    public void customize(Map<String, Object> hibernateProperties) {
        Validator validator = provider.getIfUnique();
        if (validator != null) {
            hibernateProperties.put("javax.persistence.validation.factory", validator);
        }
    }
}

Что-то вроде этого должно связать существующий валидатор с гибернацией, и при этом он будет использовать автоматическое соединение.

ПРИМЕЧАНИЕ: Вам не нужно использовать @Component на валидаторе, поскольку автоматическое подключение встроено в фабрику валидаторов перед возвратом экземпляра Validator.

0 голосов
/ 07 мая 2018

Ответ довольно большой, чтобы опубликовать здесь. Пожалуйста, проверьте эту статью в S.O, чтобы помочь вам с. Это должно помочь вам начать работу.

Проверка пользовательского валидатора с автоматическим подключением пружины

Проблема находится в спящем режиме, и вы никак не узнаете определение весны. Однако вы можете сделать так, чтобы сущности были осведомлены о любом типе javax.validation типов. Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...