以下のようにコンテナからInjectionされた値(Bean)を使ったカスタムValidatorがあったとする。
/**
* コンテナで"hoge"に登録された文字列と一致するか検証する。
*/
public class MyConstraintValidator implements ConstraintValidator<MyConstraint, String> {
@Autowired
private String hoge;
@Override
public void initialize(MyConstraint paramA) {
}
@Override
public boolean isValid(String value, ConstraintValidatorContext paramConstraintValidatorContext) {
Objects.requireNonNull(hoge);
return Objects.equals(value, hoge);
}
}
このValidatorにInjectionして使うには、Springのドキュメントでここらへんを見ると以下のような設定が必要になる。
<bean id="validator"
class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>
@Configurationなクラスで設定する場合はこうなる。
@Bean
public javax.validation.Validator localValidatorFactoryBean() {
return new LocalValidatorFactoryBean();
}
コントローラでバリデーションする場合なんかには上記だけでも良いが、Hibernateで使う場合には以下の設定でEntityManagerFactoryにValidatorの参照を渡す必要がある。
http://stackoverflow.com/questions/2712345/jsr-303-dependency-injection-and-hibernate
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="jpaPropertyMap">
<map>
<entry key="javax.persistence.validation.factory" value-ref="validator" />
</map>
</property>
</bean>
これをSpring Bootで設定する場合、SpringBootのドキュメントでここを見るとapplication.propertiesでspring.jpa.properties.*
にJPAプロパティを指定すればいいのだがなんか嫌な予感。。。
spring.jpa.properties.javax.persistence.validation.factory=validator
これでは**"validator"という文字列**を設定しているだけなのでエラーになってしまう。試しにクラス名を指定してみてもダメ。
Caused by: org.hibernate.cfg.beanvalidation.IntegrationException: Given object was not an instance of javax.validation.ValidatorFactory[java.lang.String]
Beanの参照を設定するにはプロパティファイルではだめぽなので@Configurationなクラスで設定するしかなさそう。
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(
EntityManagerFactoryBuilder builder, DataSource dataSource, JpaProperties jpaProperties) {
LocalContainerEntityManagerFactoryBean factory = builder
.dataSource(dataSource)
.packages(Application.class)
.persistenceUnit("default")
.properties(jpaProperties.getHibernateProperties(dataSource))
.build();
Map<String, Object> jpaPropertyMap = new HashMap<>();
jpaPropertyMap.put("javax.persistence.validation.factory", validator());
factory.setJpaPropertyMap(jpaPropertyMap);
return factory;
}
LocalContainerEntityManagerFactoryBeanの生成部分はJpaBaseConfiguration.entityManagerFactory()のソースを参考にした。
やりたい事はjpaPropertyMap.put("javax.persistence.validation.factory", validator();
の1行だけなんだけど、もっといいやり方はないんだろうか?