Java @Autowiredbean在控制器上与@Valid一起工作,但在CRUD存储库中失败

Java @Autowiredbean在控制器上与@Valid一起工作,但在CRUD存储库中失败,java,spring,spring-mvc,Java,Spring,Spring Mvc,我正在开发一个带有用户注册表单的Spring MVC+Hibernate+JPA应用程序,我决定使用JSR-303验证程序来检查数据库中是否已经存在用户名: public class UniqueUsernameValidator implements ConstraintValidator<VerifyUniqueUsername, String> { @Autowired UserService userService; @Override p

我正在开发一个带有用户注册表单的Spring MVC+Hibernate+JPA应用程序,我决定使用JSR-303验证程序来检查数据库中是否已经存在用户名:

public class UniqueUsernameValidator implements ConstraintValidator<VerifyUniqueUsername, String> {

    @Autowired
    UserService userService;

    @Override
    public void initialize(VerifyUniqueUsername constraintAnnotation) {     
    }

    @Override
    public boolean isValid(String username, ConstraintValidatorContext context) {                       

        return  username!=null &&  userService.findByUsername(username) == null;        
    }
}
我目前面临的问题是,在我验证了我的
User
对象后,我调用:

userService.save(user);
它实现了
crudepository
,我得到了一个
NullPointerException
。出于某种原因,在验证控制器时会注入
UserService
,但调用
crudepository.save()
时不会注入

我看到类似的帖子,比如: 这是: 但我想知道以前是否有人遇到过这种情况。我认为注入bean来访问验证器上的数据库是相当常见的

作为一种解决方法,我在
userService
上添加了一个null检查,但感觉不对

  • 这是预期的行为吗?在调用
    crudepository.save()
    之前是否支持激发这些验证
  • 是否支持我“手动”处理休眠事件?在这种情况下,
    预插入

  • 当响应save方法调用验证逻辑时,它由hibernate完成。验证程序对象是由hibernate创建的,因此spring@AutoWired将无法工作


    解决此问题的一个选项是使用@Configurable注释并启用加载时编织,以确保即使hibernate实例化验证器对象,spring也能将依赖项注入其中。

    我最终通过指示spring的
    EntityManagerFactoryBean
    使用我的验证器bean来解决此问题(更准确地说,hibernate现在将使用Spring的验证器):


    这解决了验证程序使用finder函数触发hibernate刷新的问题,而hibernate刷新又触发了验证程序,导致StackOverflower错误。

    谢谢你的建议,我对Spring还比较陌生,我会在Google上搜索@Configurable,然后再联系你们。谢谢。我运气不好,如果你能找到我的话请告诉我在哪里可以读到更多关于这方面的内容,那就太好了。谢谢!-这个问题有关于如何设置@Configurable的更多细节。它用于实体-验证程序也应该如此。-关于如何设置@Configurable的另一个例子我一直使用xml配置并解决了这个问题,我会在得到答案后发布答案谢谢
    userService.save(user);
    
    <bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
            <property name="dataSource" ref="dataSource" />
            <property name="jpaVendorAdapter">
                <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
            </property>        
            <property name="packagesToScan" value="some.packages"/>
            <property name="jpaPropertyMap">
                <map>
                    <entry key="javax.persistence.validation.factory" value-ref="validator"  />           
                </map>
            </property>
            <property name="jpaProperties">
                <props>
                    <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
                    <prop key="hibernate.max_fetch_depth">3</prop>
                    <prop key="hibernate.jdbc.fetch_size">50</prop>
                    <prop key="hibernate.jdbc.batch_size">10</prop>
                    <prop key="hibernate.show_sql">true</prop>              
                </props>        
            </property>
        </bean>  
    
    public class UniqueUsernameValidator implements ConstraintValidator<UniqueUsername, String> {
    
        @PersistenceContext
        private EntityManager em;
    
        @Autowired
        UserService userService;
    
        @Override
        public void initialize(UniqueUsername constraintAnnotation) {       
        }
    
        @Override
        public boolean isValid(String username, ConstraintValidatorContext context) {
            try { 
                em.setFlushMode(FlushModeType.COMMIT);          
                return userService.findByUsername(username) == null;
    
                } finally { 
               em.setFlushMode(FlushModeType.AUTO);
               }    
        }
    }