Hibernate @Sessionfactory.getCurrentSession.merge调用ConstraintValidator时,ConstraintValidator中的自动连线bean为null

Hibernate @Sessionfactory.getCurrentSession.merge调用ConstraintValidator时,ConstraintValidator中的自动连线bean为null,hibernate,spring,bean-validation,autowired,Hibernate,Spring,Bean Validation,Autowired,我刚刚用Hibernate实现了Bean验证 如果我显式调用验证器,它将按预期工作,并且连接到数据库的@autowireddaobean将按预期注入 我之前发现,我需要添加下面的语句,才能使上面的语句生效。我以前广泛使用过@autowiredbeans,但是下面的语句对于Spring管理验证器和将bean注入ConstraintValidator是必要的 <bean id="validator" class="org.springframework.validation.beanvalid

我刚刚用Hibernate实现了Bean验证

如果我显式调用验证器,它将按预期工作,并且连接到数据库的@autowireddaobean将按预期注入

我之前发现,我需要添加下面的语句,才能使上面的语句生效。我以前广泛使用过@autowiredbeans,但是下面的语句对于Spring管理验证器和将bean注入ConstraintValidator是必要的

<bean id="validator"
class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />
以下是ConstraintValidator的代码:

package com.twoh.dto.ConstraintValidation;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.twoh.dao.IQueryUtil;

@Component
public class FileTypeAndClassValidator implements ConstraintValidator<FileTypeAndClass, Object> {

    private Log logger = LogFactory.getLog(this.getClass());

    private String fileClassProperty;
    private String fileTypeProperty;

    @Autowired
    private IQueryUtil queryUtil;

    public void initialize(FileTypeAndClass constraintAnnotation) {
        this.fileClassProperty = constraintAnnotation.fileClassProperty();
        this.fileTypeProperty = constraintAnnotation.fileTypeProperty();
    }

    public boolean isValid(Object object, ConstraintValidatorContext constraintValidatorContext) {
        boolean result = true;

        logger.info("Validating ...");

        if (object == null) {
            result = false;
        } else {
            try {
                String fileClassName =  ConstraintValidatorHelper.getPropertyValue(String.class, fileClassProperty, object);
                Integer fileTypeId =  ConstraintValidatorHelper.getPropertyValue(Integer.class, fileTypeProperty, object);

                result = queryUtil.createHQLQuery((
                        "select ft.id" +
                        " from FileType ft" +
                        " where ft.id = :fileTypeId" +
                        " and ft.fileClassName = :fileClassName"
                ))
                .setParameter("fileTypeId", fileTypeId)
                .setParameter("fileClassName", fileClassName)
                .iterate().hasNext();
            } catch (Exception e) {
                logger.info(e);
            }
        }
        return result;
    }
}
包com.twoh.dto.constraint验证;
导入javax.validation.ConstraintValidator;
导入javax.validation.ConstraintValidatorContext;
导入org.apache.commons.logging.Log;
导入org.apache.commons.logging.LogFactory;
导入org.springframework.beans.factory.annotation.Autowired;
导入org.springframework.stereotype.Component;
导入com.twoh.dao.IQueryUtil;
@组成部分
公共类FileTypeAndClassValidator实现ConstraintValidator{
私有日志记录器=LogFactory.getLog(this.getClass());
私有字符串fileClassProperty;
私有字符串fileTypeProperty;
@自动连线
私人伊克瑞尤蒂尔;
公共void初始化(文件类型和类约束表示){
this.fileClassProperty=ConstraintAnotation.fileClassProperty();
this.fileTypeProperty=ConstraintAnotation.fileTypeProperty();
}
公共布尔值有效(对象对象,ConstraintValidatorContext ConstraintValidatorContext){
布尔结果=真;
logger.info(“验证…”);
if(object==null){
结果=假;
}否则{
试一试{
String fileClassName=ConstraintValidatorHelper.getPropertyValue(String.class、fileClassProperty、object);
Integer fileTypeId=ConstraintValidatorHelper.getPropertyValue(Integer.class,fileTypeProperty,object);
结果=queryUtil.createHQLQuery((
“选择ft.id”+
“来自文件类型ft”+
“其中ft.id=:fileTypeId”+
“和ft.fileClassName=:fileClassName”
))
.setParameter(“fileTypeId”,fileTypeId)
.setParameter(“fileClassName”,fileClassName)
.iterate().hasNext();
}捕获(例外e){
logger.info(e);
}
}
返回结果;
}
}

好的,在谷歌搜索了大约18小时后,我终于找到了一个网站,上面都描述了这个问题,并且有一个解决方案

在我当前的项目中,我们想构建一个定制的验证器 将检查数据库中是否已存在电子邮件地址 在使用Hibernate保存联系人实体的任何实例之前。这 验证器需要注入一个DAO来检查 数据库中是否存在电子邮件地址。令我们惊讶的是,什么 我们原以为是微风,但实际上是大风。弹簧注射 当我们的bean在 Hibernate的基于事件的验证(在我们的例子中是预插入 事件)

最后,我的spring配置结果如下所示:

...
<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>
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;

    }

}
。。。
...

好的,在谷歌搜索了大约18小时后,我终于找到了一个网站,上面都描述了这个问题,并且有一个解决方案

在我当前的项目中,我们想构建一个定制的验证器 将检查数据库中是否已存在电子邮件地址 在使用Hibernate保存联系人实体的任何实例之前。这 验证器需要注入一个DAO来检查 数据库中是否存在电子邮件地址。令我们惊讶的是,什么 我们原以为是微风,但实际上是大风。弹簧注射 当我们的bean在 Hibernate的基于事件的验证(在我们的例子中是预插入 事件)

最后,我的spring配置结果如下所示:

...
<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>
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;

    }

}
。。。
...

从2.5.1开始,您可以使用Spring framework提供的以下方法

SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(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>
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;

    }

}
公共类ValidUniqueUserEmailValidator实现ConstraintValidator,可序列化{
私有静态最终长serialVersionUID=1L;
@自动连线
私有UserDAO UserDAO;
@凌驾
公共无效初始化(ValidUniqueUserEmail ConstraintAnotation){
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
}
@凌驾
公共布尔值有效(对象值、ConstraintValidatorContext上下文){
布尔值isValid=true;
if(字符串的值实例){
字符串email=value.toString();
if(email==null | | email.equals(“”){
isValid=false;
}否则{
用户=新用户();
user.setEmail(email);
isValid=(userDAO.countByEmail(user)>0);
}
}
返回有效;
}
}

希望它能帮助大家

您可以使用Spring framework自2.5.1以来提供的以下方法

SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(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>
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;

    }

}
公共类ValidUniqueUserEmailValidator实现ConstraintValidator,可序列化{
私有静态最终长serialVersionUID=1L;
@自动连线
私有UserDAO UserDAO;
@凌驾
公共无效初始化(ValidUniqueUserEmail ConstraintAnotation){
SpringBeanAutowiringSupport.processInjectionBasedOnCu