9

봄 3.0.2, 최대 절전 모드 3.5.0, 최대 절전 모드 - 검사기 4.0.2.GAJSR-303 의존성 주입 및 최대 절전 모드

내가 사용 ConstraintValidator에 봄 종속성을 주입하는 것을 시도하고있다 :

@PersistenceContext 
private EntityManager entityManager; 

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

어느, 봄의 설명서에 따라, 허용해야 "CU :

내가 가진 애플리케이션 컨텍스트를 구성 다른 Spring 빈처럼 의존성 주입의 혜택을 누리려는 ConstraintValidators "

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

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

답변

4

그것은 유효성 검사기를 구성하기위한 고유의 메커니즘을 사용, 봄이 관여하지 않는 등, JPA2에, 퍼시스턴스 프로 바이더의 검증 메커니즘은 사전 지속, 사전 업데이트에 대한 기본적에서 맞이할 것으로 보인다. 나는 순간에 볼 수 있습니다

유일한 해결책은의 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> 

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

UPDATE :

는 그냥 완료하려면 다른 해결책은 META-INF/validation.xml에 constraint-validator-factory를 지정하는 것입니다.

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

유효성 검사기를 봄에서 가져 오는 ConstraintValidatorFactory의 고유 구현을 만드는 옵션이 있지만,이를 수행하는 확실한 방법은 없습니다.

+0

'<검증 모드> NONE'트릭을 수행합니다. 또한 사용자는 유효성 검사기를 수동으로 호출 할 필요가 없습니다. Spring은 유효성 검사를 Hibernate Validator로 전달한다. Hibernate Validator 4.1에서는 갑자기 모든 엔티티가 두 번 검증되었다는 문제점이있었습니다. 한 번 봄 (autowiring와 더불어) 그리고 한 번 HV를 통해서 (실패, autowired 때문에). 그러나 그것은 Hibernate Validator 4.0과 함께 작동했습니다. – Koraktor

+0

뿐만 아니라 "javax.persistence.validation.mode"를 "none"으로 설정하십시오. – Matt

1

또한 재산 javax.persistence.validation.factory를 사용하여 엔티티 관리자 창출 속성으로 ValidatorFactory을 통과 할 수있는 옵션이 있습니다. 이 속성에 ValidatorFactory 인스턴스가 저장된 경우 엔티티 관리자는 새 속성을 생성하는 대신이 유효성 검사기 팩토리를 사용합니다.

7

JSR-303 (참조 구현이되는 Hibernate Validator)은 사용자 정의 ConstraintValidator를 인스턴스화하지만 사실상 실제 생성을 ValidatorFactory에 위임합니다. 그렇다면 Spring의 LocalValidatorFactoryBean을 사용하여 은 응용 프로그램 전체에 걸쳐 사용자 정의 유효성 검사기에 종속성 주입이 가능하다고 생각할 수 있습니다.

엔티티 라이프 사이클 이벤트 (사전 업데이트, 사전 삽입, 사전 삭제)를 처리 할 때 Hibernate 자체가 Spring 컨텍스트에 구성된 것과 다른 ValidatorFactory를 사용한다는 점이 미묘합니다. 이것은 의도적으로 설계된 것입니다 : Hibernate Validator는 Spring을 인식하지 못하기 때문에, Hibernate에게 자체의 생성 대신에 Spring의 LocalValidatorFactoryBean을 사용하도록 지시해야합니다.

기본적으로,이 같은 귀하의 스프링 애플리케이션 컨텍스트 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> 

, 여기 함께 데모 애플리케이션을 넣었습니다 on Github README 파일은 자명 한 내용입니다.

+1

은 Hibernate 4, Spring 3.1에서 작동하지 않는다. 이벤트 리스너 등록 정보는 새 버전에서 설정할 수 없습니다. 나는 Integrators 기반 접근법도 시도하고있다. http://stackoverflow.com/a/11672377/161628. 그러나 Duplicate Event Listener 등록 오류를보고합니다. –

12

Spring 컨텍스트 인식 ValidatorFactory를 EntityManager에 삽입하는 가장 좋은 방법은 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"/> 

즐기십시오!

+0

이 질문은 흥미로운 것 같습니다. 비슷한 시나리오에서 문제를 해결할 수 없습니다. http://stackoverflow.com/questions/13599821/autowired-repository-is-null-in-custom-constraint-validator –

+0

Spring 4 + Hibernate 4.3 + HV 사용하기 5.1. 실행중인 시스템에 여러 개의 ValidationFactories가있는 문제에 대한 해결책을 찾기 위해 엄청난 시간을 들였습니다. 이것은 잘 작동합니다. –

+0

@MartinFrey 여기 같네요! 최대 절전 모드를 디버깅하여 솔루션을 찾은 후에이 페이지로 이동하십시오. 이것은 서류 미비 된 "비밀"재산으로 보인다 ... – Beccari

2
봄 4.0.5를 들어

및 최대 절전 모드 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>