由Sessionfactory.getCurrentSession.merge调用时,ConstraintValidator中的@Autowired bean null [英] @Autowired bean null in ConstraintValidator when invoked by Sessionfactory.getCurrentSession.merge

查看:110
本文介绍了由Sessionfactory.getCurrentSession.merge调用时,ConstraintValidator中的@Autowired bean null的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



如果我明确地调用验证器,它将按预期工作,并且连接到数据库的@Autowired DAO bean被注入如预期的那样。

我以前发现在上述工作之前我需要添加下面的语句。我之前已经广泛使用了@Autowired bean,但是下面的语句对于验证器是由Spring管理的,以及注入到ConstraintValidator中的bean来说是必需的。

 < bean id =validator
class =org.springframework.validation.beanvalidation.LocalValidatorFactoryBean/>

但是,如果在SessionFactory.getCurrentSession.merge期间自动调用验证器,则该bean为null。 p>

如果我通过调用javax.Validation.validate直接调用验证器,它会起作用,这让我认为我已经正确设置了Spring配置。



我已经阅读了一些人员无法获得DAO bean @Autowired的帖子,但在我的情况下,它在合并期间被调用时除外。



下面的日志输出显示验证器直接被首先调用,然后被合并操作调用。

  07.12.2011 01:58:13 INFO [http-8080-1](FileTypeAndClassValidator:isValid) - 正在验证... 
07.12.2011 01:58:13 INFO [http-8080- 1](ConstraintValidatorHelper:getPropertyValue) - propertyName = className,returnValue = com.twoh.dto.PurchaseOrder
07.12.2011 01:58:13 INFO [http-8080-1](ConstraintValidatorHelper:g etPropertyValue) - propertyName = fileTypeId,returnValue = 4
07.12.2011 01:58:13 INFO [http-8080-1](QueryUtil:createHQLQuery) - 从FileType选择ft.id ft ft.id = fileTypeId和ft.fileClassName =:fileClassName
07.12.2011 01:58:13 INFO [http-8080-1](BaseDAO:merge) - 实体:com.twoh.dto.PurchaseOrder:1036.
07.12 .2011 01:58:13 INFO [http-8080-1](FileTypeAndClassValidator:isValid) - 正在验证...
07.12.2011 01:58:13信息[http-8080-1](ConstraintValidatorHelper:getPropertyValue) - propertyName = className,returnValue = com.twoh.dto.PurchaseOrder
07.12.2011 01:58:13 INFO [http-8080-1](ConstraintValidatorHelper:getPropertyValue) - propertyName = fileTypeId,returnValue = 4
07.12.2011 01:58:13 INFO [http-8080-1](FileTypeAndClassValidator:isValid) - java.lang.NullPointerException

以下是ConstraintValidator的代码:

  package com.twoh.dto.ConstraintValidation; 

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

导入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> {

私有日志记录器= LogFactory.getLog(this.getClass());

私人字符串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);
整数fileTypeId = ConstraintValidatorHelper.getPropertyValue(Integer.class,fileTypeProperty,object);

result = queryUtil.createHQLQuery((
select ft.id+
from FileType ft+
where ft.id =:fileTypeId+
和ft.fileClassName =:fileClassName
))
.setParameter(fileTypeId,fileTypeId)
.setParameter(fileClassName,fileClassName)
。 。迭代()hasNext();
} catch(Exception e){
logger.info(e);
}
}
返回结果;
}
}


解决方案

好的在大约18个小时后,我终于遇到了一个网站,他们都描述了它有一个解决方案的问题。食谱:使用Hibernate基于事件的验证与定制的JSR-303验证器和Spring autowired注入


在我当前的项目中,我们想构建一个自定义验证器,
会检查一个在使用Hibernate保存我们的Contact实体的任何实例之前,电子邮件地址已经存在于数据库
中。这
验证器需要注入一个DAO以检查数据库中电子邮件地址的
是否存在。令我们吃惊的是,我们认为
是一件轻而易举的事情,更是一场大风。当我们的bean在
Hibernate的基于事件的验证(在我们的例子中,预插入
事件)的上下文中进行验证时,Spring的注入
根本不起作用。


最后,我的弹簧配置看起来像这样:

  ... 
< bean id =beanValidationEventListenerclass =org.hibernate.cfg.beanvalidation.BeanValidationEventListener>
< constructor-arg ref =validator/>
< constructor-arg ref =hibernateProperties/>
< / bean>

...

< util:properties id =hibernatePropertieslocation =classpath:hibernate.properties/>

< bean id =sessionFactory
class =org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean>
< property name =dataSourceref =myDataSource/>
< property name =packagesToScanvalue =com.twoh/>
< property name =hibernatePropertiesref =hibernateProperties/>
< property name =eventListeners>
< map>
< entry key =pre-insertvalue-ref =beanValidationEventListener/>
< entry key =pre-updatevalue-ref =beanValidationEventListener/>
< / map>
< / property>
< / bean>


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 injected as expected.

I had previously discovered that I needed to add the statement below before the above would work. I had made extensive use of @Autowired beans before but the statement below was necessary for the validator to be managed by Spring and the bean injected into the ConstraintValidator.

<bean id="validator"
class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />

However when the validator is called automatically during a SessionFactory.getCurrentSession.merge the bean is null.

The fact that it works if I invoke the validator directly with a call to javax.Validation.validate makes me think that I have set up the Spring configuration correctly.

I have read a number for posts where people have been unable to get the DAO bean @Autowired but in my case it is except when called during the merge.

The log output below shows the validator being called directly first and then being called as as a result of a merge operation.

07.12.2011 01:58:13  INFO [http-8080-1] (FileTypeAndClassValidator:isValid) - Validating ...
07.12.2011 01:58:13  INFO [http-8080-1] (ConstraintValidatorHelper:getPropertyValue) - propertyName=className, returnValue=com.twoh.dto.PurchaseOrder
07.12.2011 01:58:13  INFO [http-8080-1] (ConstraintValidatorHelper:getPropertyValue) - propertyName=fileTypeId, returnValue=4
07.12.2011 01:58:13  INFO [http-8080-1] (QueryUtil:createHQLQuery) - select ft.id from FileType ft where ft.id = :fileTypeId and ft.fileClassName = :fileClassName
07.12.2011 01:58:13  INFO [http-8080-1] (BaseDAO:merge) - Entity: com.twoh.dto.PurchaseOrder: 1036.
07.12.2011 01:58:13  INFO [http-8080-1] (FileTypeAndClassValidator:isValid) - Validating ...
07.12.2011 01:58:13  INFO [http-8080-1] (ConstraintValidatorHelper:getPropertyValue) - propertyName=className, returnValue=com.twoh.dto.PurchaseOrder
07.12.2011 01:58:13  INFO [http-8080-1] (ConstraintValidatorHelper:getPropertyValue) - propertyName=fileTypeId, returnValue=4
07.12.2011 01:58:13  INFO [http-8080-1] (FileTypeAndClassValidator:isValid) - java.lang.NullPointerException

Below is the code for the 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;
    }
}

解决方案

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>

这篇关于由Sessionfactory.getCurrentSession.merge调用时,ConstraintValidator中的@Autowired bean null的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆