如何让Hibernate 4.3.2使用自定义ResourceBundleMessageInterpolator(Spring 4.3.13)
我来帮你解决这个问题——你已经走对了前两步,但差了关键的一步:让Spring(以及Hibernate)真正用上你自定义的ValidatorFactory。结合你的Spring 4.3.13 + Hibernate 4.3.2环境,我们来一步步修正:
1. 确认自定义插值器的实现(已完成,可补充逻辑)
你的MyResourceBundleMessageInterpolator已经正确继承并重写了方法,这里可以明确自定义逻辑的添加位置:
public class MyResourceBundleMessageInterpolator extends ResourceBundleMessageInterpolator { @Override public String interpolate(String message, Context context, Locale locale) { // 在这里添加你的自定义插值逻辑,比如: // 1. 替换特定业务占位符 // 2. 给消息添加统一前缀/后缀 // 3. 扩展多语言适配规则 // 先调用父类完成默认插值逻辑 String defaultInterpolated = super.interpolate(message, context, locale); // 示例:给所有验证消息添加自定义标记 return "[CustomValidation] " + defaultInterpolated; } }
2. 用Spring的LocalValidatorFactoryBean替代手动构建ValidatorFactory
你之前手动创建了ValidatorFactory但没有交给Spring管理,Spring默认会自己构建默认的ValidatorFactory。正确的做法是通过Spring提供的LocalValidatorFactoryBean来配置——它是Spring与Hibernate Validator的官方集成桥梁:
方式1:Java Config配置
创建一个配置类,注册LocalValidatorFactoryBean并注入你的自定义插值器:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean; @Configuration public class ValidationConfig { @Bean public LocalValidatorFactoryBean validator() { LocalValidatorFactoryBean validatorFactoryBean = new LocalValidatorFactoryBean(); // 注入自定义消息插值器 validatorFactoryBean.setMessageInterpolator(new MyResourceBundleMessageInterpolator()); return validatorFactoryBean; } }
方式2:XML配置(如果项目使用XML配置)
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"> <property name="messageInterpolator"> <bean class="com.yourpackage.MyResourceBundleMessageInterpolator"/> </property> </bean>
3. 让Hibernate JPA验证也使用该插值器(可选)
如果你需要Hibernate在JPA实体操作(比如persist()/merge())时触发的验证也用上自定义插值器,需要在JPA配置中指定使用Spring管理的ValidatorFactory:
Java Config配置EntityManagerFactory
import org.springframework.context.annotation.Bean; import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; import javax.sql.DataSource; import java.util.Properties; @Configuration public class JpaConfig { @Bean public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource, LocalValidatorFactoryBean validator) { LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); em.setDataSource(dataSource); em.setPackagesToScan("com.yourpackage.entity"); // 替换为你的实体类包路径 em.setJpaVendorAdapter(new HibernateJpaVendorAdapter()); Properties jpaProperties = new Properties(); // 指定使用Spring管理的ValidatorFactory jpaProperties.put("javax.persistence.validation.factory", validator); em.setJpaProperties(jpaProperties); return em; } }
为什么之前的配置不生效?
你之前的MyResourceBundleMessageInterpolatorConfigurer手动构建了ValidatorFactory,但这个对象并没有被Spring或Hibernate引用。Spring的验证框架和Hibernate JPA默认会使用自己构建的默认ValidatorFactory,只有通过LocalValidatorFactoryBean配置的实例才会被整个Spring上下文接管,进而被Hibernate使用。
内容的提问来源于stack exchange,提问作者Krzysztof Majewski

