【问题标题】:Cannot use @Autowired within ConstraintValidator - gives NPE不能在 ConstraintValidator 中使用 @Autowired - 给出 NPE
【发布时间】:2014-09-11 18:27:44
【问题描述】:

我有一个自定义的 ConstraintValidator 来验证 @TelephoneNumber 注释,如下所示:

@Component
public class TelephoneNumberValidator implements ConstraintValidator<TelephoneNumber, String> {

    @Autowired
    ValidationHelper validationHelper;

    @Override
    public void initialize(TelephoneNumber telephoneNumber) { }

    @Override
    public boolean isValid(String telephoneNumber, ConstraintValidatorContext cxt) {

        if(telephoneNumber == null) {
            return true;
        } else {
            return validationHelper.isTelephoneNumber(telephoneNumber);
        }
    }
}

如您所见,它会自动装配一个 ValidationHelper 对象,该对象被标记为 @Component

在我的@Repository 中,每当我通过sessionFactory.getCurrentSession().persist(myobject); 持久化我的对象时,我都会得到一个NPE,因为validationHelper 为空。

我的休眠配置是:

@Configuration
@EnableTransactionManagement
@ComponentScan(basePackages="uk.co.domain.repositories")
public class HibernateConfig {

    static final String DRIVER_CLASS = "com.mysql.jdbc.Driver";
    static final String URL = "jdbc:mysql://localhost:3306/mydatabase";
    static final String USERNAME = "user";
    static final String PASSWORD = "pass";

    @Bean
    public DataSource dataSource() {

        BasicDataSource dataSource = new org.apache.commons.dbcp2.BasicDataSource();
        dataSource.setDriverClassName(DRIVER_CLASS);
        dataSource.setUsername(USERNAME);
        dataSource.setPassword(PASSWORD);
        dataSource.setUrl(URL);
        dataSource.setInitialSize(10);

        return dataSource;
    }

    @Bean
    public LocalSessionFactoryBean sessionFactory() {

        LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
        sessionFactory.setDataSource(dataSource());
        sessionFactory.setPackagesToScan(new String[] { "uk.co.domain.models" });

        return sessionFactory;
    }

    @Bean
    public HibernateTransactionManager transactionManager() {

        HibernateTransactionManager txManager = new HibernateTransactionManager();
        txManager.setSessionFactory(sessionFactory().getObject());

        return txManager;
    }

    @Bean
    public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {

        return new PersistenceExceptionTranslationPostProcessor();
    }
}

我已经配置了LocalValidatorFactoryBean,如下:

@Configuration
@ComponentScan(basePackages="uk.co.domain.validators")
public class ValidatorConfig {

    @Bean
    public MethodValidationPostProcessor methodValidationPostProcessor() {
        MethodValidationPostProcessor methodValidationPostProcessor = new MethodValidationPostProcessor();
        methodValidationPostProcessor.setValidator(validator());
        return methodValidationPostProcessor;
    }

    @Bean
    public LocalValidatorFactoryBean validator() {
        LocalValidatorFactoryBean localValidatorFactoryBean = new LocalValidatorFactoryBean();
        return localValidatorFactoryBean;
    }
}

但是这并没有解决问题。 MVC 表单验证工作得很好,只是 Hibernate 持久化操作失败了。

我是否需要告诉 Hibernate 使用这个验证器?我将不胜感激。

【问题讨论】:

    标签: java spring hibernate-validator spring-validator


    【解决方案1】:

    正在使用的验证器实例可能不是 Spring 管理的 bean。我怀疑 Hibernate 正在创建您的验证器的实例并使用该实例而不是您在 Spring 中创建的实例。

    您要么需要让 Hibernate 使用 Spring 托管实例,要么找到解决方法(要么在验证器中自己实例化它)。考虑使用静态方法 - 当我验证电话号码时,验证方法通常不需要进行任何数据库调用或任何需要大量依赖注入的操作。

    【讨论】:

    • 感谢您的回复。我需要在我的验证器中自动装配,因为 isTelephoneNumber 调用数据库,所以它不能是静态的。我还需要在其他验证器中自动连接其他服务。你知道如何让我休眠以使用 spring 管理的实例吗?
    • 我不认为你可以。当 Spring 创建 ValidationHelper 时,您可以通过初始化单例静态实例来使用单例模式。然后在您的验证器中,调用ValidationHelper.getInstance() 来获取实例。 ...这有点难看,但我不知道是否有办法告诉 Hibernate 使用 Spring 管理的实例。
    猜你喜欢
    • 2018-04-25
    • 2011-09-28
    • 1970-01-01
    • 1970-01-01
    • 2015-09-29
    • 1970-01-01
    • 2020-12-16
    • 2018-07-15
    • 1970-01-01
    相关资源
    最近更新 更多