@Autowired bean-компонент null в ConstraintValidator при вызове Sessionfactory.getCurrentSession.merge - PullRequest
1 голос
/ 07 декабря 2011

Я только что реализовал проверку бина в Hibernate.

Если я вызываю валидатор явно, он работает как положено, и мой компонент DAO @Autowired, который подключается к БД, вводится как ожидалось.

Ранее я обнаружил, что мне нужно добавить приведенное ниже утверждение, прежде чем вышеприведенное сработает. Раньше я широко использовал bean-компоненты @Autowired, но нижеприведенное утверждение было необходимо для управления валидатором в Spring и для добавления бина в ConstraintValidator.

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

Однако, когда валидатор вызывается автоматически во время SessionFactory.getCurrentSession.merge, бин имеет значение null.

Тот факт, что это работает, если я вызываю валидатор напрямую с помощью вызова javax.Validation.validate, заставляет меня думать, что я правильно настроил конфигурацию Spring.

Я прочитал номер для постов, где люди не смогли получить bean-компонент DAO @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;
    }
}

Ответы [ 2 ]

6 голосов
/ 08 декабря 2011

Хорошо, после примерно 18 часов поиска в Google я, наконец, наткнулся на сайт, на котором оба описали проблему, решение которой есть. Рецепт: Использование проверки подлинности на основе событий Hibernate с настраиваемыми валидаторами JSR-303 и автоматическим внедрением Spring

В моем текущем проекте мы хотели создать специальный валидатор, который проверял бы,адрес электронной почты уже существовал в базе данных до сохранения любого экземпляра нашего объекта Contact с помощью Hibernate.Этому валидатору необходимо было ввести DAO для проверки наличия адреса электронной почты в базе данных.К нашему удивлению, то, что мы считали бризом, было скорее штормом.Впрыск Spring не работал вообще, когда наш 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>
5 голосов
/ 31 июля 2013

Вы можете использовать следующий метод, предоставляемый Spring Framework, так как 2.5.1

SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);

намного чище, так как вам не нужно устанавливать какой-либо слушатель / свойство в вашем приложении.

Ваш код будет выглядеть так:

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;

    }

}

Надеюсь, это поможет вам, ребята

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...