如何将springrepo注入hibernate拦截器

如何将springrepo注入hibernate拦截器,spring,hibernate,interceptor,Spring,Hibernate,Interceptor,我们正在构建一个应用程序,需要将实体更新记录到历史记录表中。我正试图通过hibernate拦截器来实现这一点,我们能够管理所有的更改,但在将它们插入审计表时遇到困难 我的JPA配置 public class JPAConfiguration { ---- @Bean(name = "entityManagerFactory") public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean() throws SQL

我们正在构建一个应用程序,需要将实体更新记录到历史记录表中。我正试图通过hibernate拦截器来实现这一点,我们能够管理所有的更改,但在将它们插入审计表时遇到困难

我的JPA配置

public class JPAConfiguration {
 ----
 @Bean(name = "entityManagerFactory")
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean() throws SQLException {
    LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
    factoryBean.setDataSource(dataSource());
    factoryBean.setPackagesToScan(new String[] {"com.yyy.persist"});

    HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
    vendorAdapter.setShowSql(true);
    // thsi is required in order to enable Query DSL
    vendorAdapter.setDatabasePlatform("org.hibernate.dialect.Oracle10gDialect");
    factoryBean.setJpaVendorAdapter(vendorAdapter);
   // factoryBean.setMappingResources(mappingResources);
    // adding hibernate interceptor

    Properties jpaProperties = new Properties();
    jpaProperties.setProperty("hibernate.ejb.interceptor", "com.yyy.admin.service.AuditInterceptor");
    factoryBean.setJpaProperties(jpaProperties);
    return factoryBean;
}
我的拦截器

public class AuditInterceptor extends EmptyInterceptor {
public boolean onFlushDirty(Object entity, Serializable id, Object[] currentState, Object[] previousState,
        String[] propertyNames, Type[] types) {

     if ( entity instanceof Auditable ) {
    // updates++;

    for (int i = 0; i < propertyNames.length; i++) {

        if ((currentState[i] == null && previousState[i] != null)
                || (currentState[i] != null && previousState[i] == null) || (currentState[i] != null
                        && previousState[i] != null && !currentState[i].equals(previousState[i]))) {

            AuditLog audit = new AuditLog();
            audit.setAction("UPDATE");
            audit.setFieldChanged(propertyNames[i]);
            audit.setOldvalue(previousState[i] != null ? previousState[i].toString() : "");
            audit.setNewvalue(currentState[i] != null ? currentState[i].toString() : "");
            audit.setTimeStamp(new Date());
            audit.setUsername(userName);

            entities.add(audit);
        }
    }

    // iterate elements on the report build a entity
 }
    return false;
}

public void afterTransactionCompletion(Transaction tx) {

    if (tx.wasCommitted()) {
if (entities != null) {
            for (AuditLog e : entities) {
                System.out.println(e);
                //.save(e);
            }
            entities = new ArrayList<AuditLog>();
        }
    }
     }
公共类AuditInterceptor扩展了EmptyInterceptor{
公共布尔值onFlushDirty(对象实体,可序列化id,对象[]当前状态,对象[]先前状态,
字符串[]属性名称,类型[]类型){
if(可审核的实体实例){
//更新++;
for(int i=0;i
}


在方法afterTransactionCompletion中,我需要将所有审计实体写入DB,Autowire不工作,因为这不是spring管理的bean,是否有任何方法可以使用此方法获取DB会话,以便我可以执行插入。

将Springbean注入非Spring托管类的典型解决方案是通过静态资源持有者。例如,您有一个名为StaticServiceHolder的类,annotate is with
@Component
,然后通过setter为要注入的Springbean创建静态字段。比如:

@Component
public class StaticServiceHolder
{
    public static AuditService auditService;

    @Autowired
    public void setAuditService(AuditService auditService)
    {
        StaticServiceHolder.auditService = auditService;
    }
}
或者,如果需要注入大量这些内容,则可以自动连接
ApplicationContext
。这样你就可以得到任何你需要的豆子

@Component
public class ApplicationContextHolder implements ApplicationContextAware {
    public static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext ctx) {
        ApplicationContextHolder.applicationContext = ctx;
    }
}

....
//in your hibernate interceptor
YourAuditService auditService = ApplicationContextHolder.applicationContext.getBean(YourAuditService.class);
auditService.saveAuditLog();
无论哪种方式,只要您使用的服务是事务性的,您就应该能够在DB中持久保存您的内容。希望这对你有用

对于事务管理器设置:

@Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory emf)
{
    JpaTransactionManager transactionManager = new JpaTransactionManager();
    transactionManager.setEntityManagerFactory(emf);

    return transactionManager;
}

将Springbean注入非Spring托管类的典型解决方案是通过静态资源持有者。例如,您有一个名为StaticServiceHolder的类,annotate is with
@Component
,然后通过setter为要注入的Springbean创建静态字段。比如:

@Component
public class StaticServiceHolder
{
    public static AuditService auditService;

    @Autowired
    public void setAuditService(AuditService auditService)
    {
        StaticServiceHolder.auditService = auditService;
    }
}
或者,如果需要注入大量这些内容,则可以自动连接
ApplicationContext
。这样你就可以得到任何你需要的豆子

@Component
public class ApplicationContextHolder implements ApplicationContextAware {
    public static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext ctx) {
        ApplicationContextHolder.applicationContext = ctx;
    }
}

....
//in your hibernate interceptor
YourAuditService auditService = ApplicationContextHolder.applicationContext.getBean(YourAuditService.class);
auditService.saveAuditLog();
无论哪种方式,只要您使用的服务是事务性的,您就应该能够在DB中持久保存您的内容。希望这对你有用

对于事务管理器设置:

@Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory emf)
{
    JpaTransactionManager transactionManager = new JpaTransactionManager();
    transactionManager.setEntityManagerFactory(emf);

    return transactionManager;
}

我知道这有点晚了,但可能对其他人有帮助。 通过使用Springbean而不是类名作为
“hibernate.ejb.interceptor”
的值,hibernate获取Springbean而不是实例化一个新类

更多信息请访问:
我知道这有点晚了,但可能对其他人有帮助。 通过使用Springbean而不是类名作为
“hibernate.ejb.interceptor”
的值,hibernate获取Springbean而不是实例化一个新类

更多信息请访问:

谢谢您的回复。应用程序上下文的第二种方法在我的情况下不起作用。。我不知道我在那里做错了什么。。尝试使用first appraochI可以使用静态持有人注入回购。。有些人认为数据无法保存到数据库中。我做了春季JPA回购交易,但仍然不走运。。有什么想法吗?嗯,我想这真的是另一个话题。它与您的
TransactionManager
设置相关。让我来帮你。。。。最后,我更新了典型TransactionManager java配置的答案。只要一个事务启动,持久化就应该工作。通常,您不会使repo/dao层成为事务层,而是使服务层成为事务层,这样一个事务就可以同时覆盖多个db调用和成功/失败。但是为了测试的目的,我想没问题。嗨,里昂,第一个问题解决了。。仍然无法保存记录。。正如你提到的,我将开始新的问题,并将其解决。谢谢你的帮助。谢谢你的回复。应用程序上下文的第二种方法在我的情况下不起作用。。我不知道我在那里做错了什么。。尝试使用first appraochI可以使用静态持有人注入回购。。有些人认为数据无法保存到数据库中。我做了春季JPA回购交易,但仍然不走运。。有什么想法吗?嗯,我想这真的是另一个话题。它与您的
TransactionManager
设置相关。让我来帮你。。。。最后,我更新了典型TransactionManager java配置的答案。只要一个事务启动,持久化就应该工作。通常,您不会使repo/dao层成为事务层,而是使服务层成为事务层,这样一个事务就可以同时覆盖多个db调用和成功/失败。但是为了测试的目的,我想没问题。嗨,里昂,第一个问题解决了。。仍然无法保存记录。。正如你提到的,我将开始新的问题,并将其解决。谢谢你的帮助。