以几个线程作为参考,我最终得到了以下解决方案:
我正在使用 Spring-Boot 1.2.3.RELEASE(这是目前的 ga)
我的用例是this bug (DATAREST-373) 中描述的。
我需要能够在创建时对User@Entity的密码进行编码,并在保存时具有特殊逻辑。使用@HandleBeforeCreate 并检查@Entity id 的0L 相等性非常简单。
为了保存,我实现了一个Hibernate Interceptor,它扩展了一个EmptyInterceptor
@Component
class UserInterceptor extends EmptyInterceptor{
@Autowired
PasswordEncoder passwordEncoder;
@Override
boolean onFlushDirty(Object entity, Serializable id, Object[] currentState, Object[] previousState, String[] propertyNames, Type[] types) {
if(!(entity instanceof User)){
return false;
}
def passwordIndex = propertyNames.findIndexOf { it == "password"};
if(entity.password == null && previousState[passwordIndex] !=null){
currentState[passwordIndex] = previousState[passwordIndex];
}else{
currentState[passwordIndex] = passwordEncoder.encode(currentState[passwordIndex]);
}
return true;
}
}
使用 spring boot 文档说明
在创建本地 EntityManagerFactory 时,spring.jpa.properties.* 中的所有属性都作为普通 JPA 属性(去除前缀)传递。
正如许多参考资料所述,我们可以在 Spring-Boot 配置中使用 spring.jpa.properties.hibernate.ejb.interceptor 定义我们的拦截器。但是我无法让@Autowire PasswordEncoder 工作。
所以我求助于使用HibernateJpaAutoConfiguration 并覆盖protected void customizeVendorProperties(Map<String, Object> vendorProperties)。这是我的配置。
@Configuration
public class HibernateConfiguration extends HibernateJpaAutoConfiguration{
@Autowired
Interceptor userInterceptor;
@Override
protected void customizeVendorProperties(Map<String, Object> vendorProperties) {
vendorProperties.put("hibernate.ejb.interceptor",userInterceptor);
}
}
自动装配 Interceptor 而不是让 Hibernate 实例化它是让它工作的关键。
现在困扰我的是逻辑一分为二,但希望一旦 DATAREST-373 得到解决,那么这将是不必要的。