9

春 3.0.2、休止状態 3.5.0、休止状態バリデーター 4.0.2.GA

以下を使用して、Spring の依存関係を ConstraintValidator に注入しようとしています。

@PersistenceContext
private EntityManager entityManager;

アプリケーション コンテキストを次のように構成しました。

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

Spring のドキュメントによると、「カスタム ConstraintValidators が他の Spring Bean と同様に依存性注入の恩恵を受ける」ことができるはずです</p>

デバッガー内で、Spring が getBean を呼び出して ConstraintValidator を作成していることがわかります。後でフラッシュが preInsert をトリガーすると、別の ConstraintValidator が作成されて呼び出されます。問題は、この新しい ConstraintValidator 内で EntityManager が null であることです。ConstraintValidator 内に他の依存関係を注入しようとしましたが、これらは常に null です。

ConstraintValidator に依存関係を注入できるかどうかは誰にもわかりませんか?

4

6 に答える 6

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"/>

楽しみ!

于 2011-05-25T14:23:04.110 に答える
7

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 ファイルは一目瞭然です。

于 2010-11-24T04:28:07.453 に答える
4

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 以前の世界と同様に、バリデーターを手動で呼び出す必要があります。

アップデート:

完全にするために、別の解決策としてconstraint-validator-factory、META-INF/validation.xml で a を指定します。

これがSpringのものであればとてもいいのですSpringConstraintValidatorFactoryが、残念ながら、コンストラクターに渡す必要がありAutowireCapableBeanFactoryますが、引数なしのコンストラクターを持つクラスはJPA2によってここで期待されています。

これにより、独自の実装を作成ConstraintValidatorFactoryしてSpringからバリデーターを引き出すオプションが残されますが、それを行うためのクリーンな方法は見当たりません。

于 2010-04-28T11:00:45.193 に答える
2

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>
于 2014-09-01T13:17:49.803 に答える
1

また、プロパティjavax.persistence.validation.factoryを使用してValidatorFactoryをエンティティ マネージャの作成にプロパティとして渡すオプションもあります。このプロパティに ValidatorFactory インスタンスが格納されている場合、エンティティ マネージャーは新しいバリデータ ファクトリを作成する代わりに、このバリデータ ファクトリを使用します

于 2010-05-11T15:48:39.500 に答える