@Autowired bean null in ConstraintValidator when invoked by Sessionfactory.getCurrentSession.merge

后端 未结 2 1025
[愿得一人]
[愿得一人] 2021-02-11 08:47

I have just implemented Bean Validation with Hibernate.

If I call the validator explicitly it works as expected and my @Autowired DAO bean that connects to the DB is inj

相关标签:
2条回答
  • 2021-02-11 09:12

    Ok after about 18hrs of googling I finally came across a site that both described the problem it has a solution. Recipe: Using Hibernate event-based validation with custom JSR-303 validators and Spring autowired injection

    In my current project, we wanted to build a custom validator that would check if an e-mail address already existed in the database before saving any instance of our Contact entity using Hibernate. This validator needed a DAO to be injected in order to check for the existence of the e-mail address in the database. To our surprise, what we thought would be a breeze was more of a gale. Spring’s injection did not work at all when our bean was validated in the context of Hibernate’s event-based validation (in our case, the pre-insert event).

    In the end my spring configuration ended up looking like this:

    ...
    <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />
    <bean id="beanValidationEventListener" class="org.hibernate.cfg.beanvalidation.BeanValidationEventListener">
        <constructor-arg ref="validator"/>
        <constructor-arg ref="hibernateProperties"/>
    </bean>
    
    ...
    
    <util:properties id="hibernateProperties" location="classpath:hibernate.properties"/>
    
    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
        <property name="dataSource" ref="myDataSource" />
        <property name="packagesToScan" value="com.twoh" />
        <property name="hibernateProperties" ref="hibernateProperties"/>
        <property name="eventListeners">
            <map>
                <entry key="pre-insert" value-ref="beanValidationEventListener" />
                <entry key="pre-update" value-ref="beanValidationEventListener" />
            </map>
        </property>
    </bean>
    
    0 讨论(0)
  • 2021-02-11 09:21

    You can use the following method provided by Spring framework since 2.5.1

    SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
    

    it's much cleaner since you don't have to set any listener/property across your application.

    You code will look like this:

    public class ValidUniqueUserEmailValidator implements ConstraintValidator<ValidUniqueUserEmail, Object>, Serializable {
    
        private static final long serialVersionUID = 1L;
    
        @Autowired
        private UserDAO userDAO;
    
        @Override
        public void initialize(ValidUniqueUserEmail constraintAnnotation) {
            SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
        }
    
        @Override
        public boolean isValid(Object value, ConstraintValidatorContext context) {
            boolean isValid = true;
            if (value instanceof String) {
                String email = value.toString();
                if (email == null || email.equals("")) {
                    isValid = false;
                }else{
                    User user = new User();
                    user.setEmail(email);
                    isValid = (userDAO.countByEmail(user) > 0);
                }
            }
            return isValid;
    
        }
    
    }
    

    Hope it helps you guys out

    0 讨论(0)
提交回复
热议问题