当 Sessionfactory.getCurrentSession.merge 调用时,ConstraintValidator 中的 @Autowired bean null
我刚刚使用 Hibernate 实现了 Bean 验证。
如果我显式调用验证器,它会按预期工作,并且连接到数据库的 @Autowired DAO bean 将按预期注入。
我之前发现我需要添加下面的语句才能使上面的内容起作用。我之前广泛使用过 @Autowired beans,但是下面的语句对于由 Spring 管理验证器并将 bean 注入 ConstraintValidator 是必要的。
<bean id="validator"
class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />
但是,当在 SessionFactory.getCurrentSession.merge 期间自动调用验证器时,bean 为 null。
事实上,如果我直接通过调用 javax.Validation.validate 来调用验证器,它就会起作用,这让我认为我已经正确设置了 Spring 配置。
我读过一些帖子,其中人们无法获得 DAO bean @Autowired,但就我而言,除非在合并期间调用。
下面的日志输出显示验证器首先被直接调用,然后作为合并操作的结果被调用。
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
下面是 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;
}
}
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;
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您可以使用 Spring 框架从 2.5.1 开始提供的以下方法,
它更加简洁,因为您不必在应用程序中设置任何侦听器/属性。
您的代码将如下所示:
希望对你们有所帮助
You can use the following method provided by Spring framework since 2.5.1
it's much cleaner since you don't have to set any listener/property across your application.
You code will look like this:
Hope it helps you guys out
好吧,经过大约 18 个小时的谷歌搜索,我终于找到了一个网站,该网站既描述了问题,又提供了解决方案。 配方:使用 Hibernate 基于事件的验证与自定义 JSR-303 验证器和Spring自动装配注入
最后我的 spring 配置看起来像这样:
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 the end my spring configuration ended up looking like this: