복붙노트

[SPRING] JSR-303 의존성 주입 및 절전

SPRING

JSR-303 의존성 주입 및 절전

스프링 3.0.2, 최대 절전 모드 3.5.0, Hibernate-Validator 4.0.2.GA

Spring 의존성을 ConstraintValidator에 삽입하려고한다.

@PersistenceContext
private EntityManager entityManager;

응용 프로그램 컨텍스트를 다음과 같이 구성했습니다.

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

Spring의 문서에 따르면, "Custom ConstraintValidators가 다른 Spring bean처럼 의존성 주입의 이점을 얻을 수 있도록 허용해야한다"

디버거 내에서 Spring이 getBean을 호출하여 ConstraintValidator를 생성하는 것을 볼 수 있습니다. 나중에 플러시가 preInsert를 트리거하면 다른 ConstraintValidator가 만들어져 호출됩니다. 문제는이 새로운 ConstraintValidator 내에서 EntityManager가 null이라는 것입니다. ConstraintValidator 내에서 다른 종속성을 주입하려고 시도했지만 항상 null입니다.

누구든지 ConstraintValidator에 종속성을 주입 할 수 있는지 알고 있습니까?

해결법

  1. ==============================

    1.EntityManager 내에 Spring 컨텍스트 인식 ValidatorFactory를 삽입하는 가장 좋은 방법은 javax.persistence.validation.factory 속성을 사용하는 것이다. 구성은 다음과 같습니다.

    EntityManager 내에 Spring 컨텍스트 인식 ValidatorFactory를 삽입하는 가장 좋은 방법은 javax.persistence.validation.factory 속성을 사용하는 것이다. 구성은 다음과 같습니다.

    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
     <property name="dataSource" ref="dataSource" />
     <property name="jpaVendorAdapter">
      <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
       <property name="databasePlatform" value="org.hibernate.dialect.HSQLDialect" />              
      </bean>
     </property>
     <property name="jpaPropertyMap">
      <map>
       <entry key="javax.persistence.validation.factory" value-ref="validator" />               
      </map>
     </property>
    </bean>
    
    <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>
    

    즐겨!

  2. ==============================

    2.JSR-303 (참조 구현이되는 Hibernate Validator)은 커스텀 ConstraintValidator를 인스턴스화하지만 실제로는 실제 생성을 ValidatorFactory에 위임합니다. 따라서 Spring의 LocalValidatorFactoryBean을 사용하면 응용 프로그램 전체에 걸쳐 사용자 정의 유효성 검사기에 대한 종속성 주입이 가능해야한다고 생각하는 것이 옳습니다.

    JSR-303 (참조 구현이되는 Hibernate Validator)은 커스텀 ConstraintValidator를 인스턴스화하지만 실제로는 실제 생성을 ValidatorFactory에 위임합니다. 따라서 Spring의 LocalValidatorFactoryBean을 사용하면 응용 프로그램 전체에 걸쳐 사용자 정의 유효성 검사기에 대한 종속성 주입이 가능해야한다고 생각하는 것이 옳습니다.

    여기서 중요한 점은, Hibernate 자체가 엔티티 생명주기 이벤트 (사전 갱신, 사전 삽입, 사전 삭제)를 처리 할 때 Spring 컨텍스트에 구성된 것과 다른 별도의 ValidatorFactory를 사용한다는 사실에 있습니다. 이것은 의도적으로 설계된 것입니다 : Hibernate Validator는 Spring을 인식하지 못하기 때문에 Hibernate에게 자체의 생성 대신 Spring의 LocalValidatorFactoryBean을 사용하도록 지시해야합니다.

    기본적으로 Spring 애플리케이션 컨텍스트 XML에는 다음과 같은 내용이 필요합니다.

    <!-- The LocalValidatorFactoryBean is able to instantiate custom validators and inject autowired dependencies. -->
    <bean id="validator"
          class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>
    
    <!--
       This is the key to link Spring's injection to Hibernate event-based validation.
       Notice the first constructor argument, this is our Spring ValidatorFactory instance.
      -->
    <bean id="beanValidationEventListener" class="org.hibernate.cfg.beanvalidation.BeanValidationEventListener">
        <constructor-arg ref="validator"/>
        <constructor-arg ref="hibernateProperties"/>
    </bean>
    
    <bean id="mySessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
        ...
    
        <!--
          A reference to our custom BeanValidationEventListener instance is pushed for all events.
          This can of course be customized if you only need a specific event to trigger validations.
        -->
        <property name="eventListeners">
            <map>
                <entry key="pre-update" value-ref="beanValidationEventListener"/>
                <entry key="pre-insert" value-ref="beanValidationEventListener"/>
                <entry key="pre-delete" value-ref="beanValidationEventListener"/>
            </map>
        </property>
    </bean>
    

    내가 그것을하는 방법을 찾기 위해 잠시 노력한 이래로, 나는 Github에 데모 어플리케이션을 함께 넣었다. README 파일은 자명하다.

  3. ==============================

    3.JPA2에서는 지속성 공급자의 유효성 검사 메커니즘이 기본적으로 사전 지속, 사전 업데이트 등에서 시작되는 것으로 보입니다.

    JPA2에서는 지속성 공급자의 유효성 검사 메커니즘이 기본적으로 사전 지속, 사전 업데이트 등에서 시작되는 것으로 보입니다.

    유효성 검사기를 구성하는 데 자체 메커니즘을 사용하므로 Spring은 관련되지 않습니다.

    지금 볼 수있는 유일한 해결책은 persistence.xml에서 즉시 사용할 수있는 JPA2 유효성 검사를 비활성화하는 것입니다.

    <persistence-unit name="persistenceUnit" transaction-type="RESOURCE_LOCAL">
      <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <properties>
          <property name="hibernate.show_sql" value="true"/>
          <!-- other props -->
        </properties>
      <validation-mode>NONE</validation-mode>
    </persistence-unit>
    

    그런 다음 Spring의 LocalValidatiorFactoryBean을 평소대로 사용하십시오. JPA2 이전의 경우처럼 수동으로 유효성 검사기를 호출해야합니다.

    최신 정보:

    이 작업을 완료하기 위해서는 META-INF / validation.xml에 제약 조건 유효성 검사기를 지정하는 것이 좋습니다.

    이것이 Spring의 SpringConstraintValidatorFactory가 될 수 있으면 좋겠지 만 불행히도 AutowireCapableBeanFactory가 생성자에 전달되어야하지만 JPA2에서는 arg 생성자가없는 클래스가 필요합니다.

    Spring에서 유효성 검사기를 가져 오는 ConstraintValidatorFactory의 자체 구현을 만드는 옵션을 남겨 둡니다.하지만이를 수행하는 확실한 방법은 없습니다.

  4. ==============================

    4.Spring 4.0.5와 Hibernate 4.3.5에서 EL으로이 문제를 해결할 수 있었다.

    Spring 4.0.5와 Hibernate 4.3.5에서 EL으로이 문제를 해결할 수 있었다.

    <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>
    ...
    <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        ...
        <property name="hibernateProperties">
            <props>
                ...
                <prop key="javax.persistence.validation.factory">#{validator}</prop>
            </props>
        </property>
    </bean>
    
  5. ==============================

    5.또한 javax.persistence.validation.factory 등록 정보를 사용하여 ValidatorFactory를 등록 정보로 전달하여 엔티티 관리자 작성에 전달하는 옵션이 있습니다. 이 프로퍼티에 포함되어있는 ValidatorFactory 인스턴스가있는 경우, 엔티티 매니저는 새로운 인스턴스를 생성하는 대신에,이 validator 팩토리를 사용합니다.

    또한 javax.persistence.validation.factory 등록 정보를 사용하여 ValidatorFactory를 등록 정보로 전달하여 엔티티 관리자 작성에 전달하는 옵션이 있습니다. 이 프로퍼티에 포함되어있는 ValidatorFactory 인스턴스가있는 경우, 엔티티 매니저는 새로운 인스턴스를 생성하는 대신에,이 validator 팩토리를 사용합니다.

  6. from https://stackoverflow.com/questions/2712345/jsr-303-dependency-injection-and-hibernate by cc-by-sa and MIT license