2016-08-10 6 views
0

エンティティの更新を履歴テーブルに記録する必要のあるアプリケーションを1つ構築しています。私はこれをHibernateインターセプタで達成しようとしています。すべての変更を取得することができますが、監査テーブルに挿入するのは困難です。この方法でSpringレポを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>(); 
     } 
    } 
    } 

}

私はこれが管理SPRINGされていないように動作していないDB、Autowireにすべての監査エンティティを記述する必要がafterTransactionCompletion Beanは、このメソッドでDBセッションを取得する方法があるので、挿入を実行できます。

答えて

1

Spring Beansを非スプリング管理クラスに挿入する典型的なソリューションは、静的リソース・ホルダです。たとえば、StaticServiceHolderというクラスがあり、annotateに@Componentがある場合は、setterを注入するSpring Beanの静的フィールドを作成します。同様に:

@Component 
public class StaticServiceHolder 
{ 
    public static AuditService auditService; 

    @Autowired 
    public void setAuditService(AuditService auditService) 
    { 
     StaticServiceHolder.auditService = auditService; 
    } 
} 

、あるいは簡単に、あなたは、これらの多くのものを持っているならば、あなたはApplicationContextをAutowireすることができ、注入される必要があります。この方法で、必要なBeanを手に入れることができます。

@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(); 

いずれかの方法で、あなたは限り、あなたは利用しているサービスがTransactionalあるとしてDBに自分のものを保持することができるはずです。あなたのためにこの作品が欲しいです。トランザクションマネージャのセットアップについては

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

    return transactionManager; 
} 
+0

感謝を:ここに見つけることが

より。アプリケーションコンテキストでの2番目のアプローチは私のケースでは機能していません。何が間違っているのかわかりません。最初のアプラックで試してみましょう –

+0

静的なホルダーを使ってレポを注入することができました。私は春のJPAレポを国境を越えて作りました。 –

+0

hmmm、それは私が考える本当に別の話題です。これは 'TransactionManager'設定に関連しています。私はあなたを助けようとしています....私は典型的なTransactionManger java設定のための答えを最後に更新しました。トランザクションが始まる限り、永続性は機能するはずです。 –

-1

私は、これは少し遅れている知っているが、他の人のために多分役立ちます。 クラス名の代わりにスプリング名を"hibernate.ejb.interceptor"の値として使うことで、hibernateは新しいクラスをインスタンス化するのではなく、spring beanを取ります。お返事のための Autowired to hibernate Interceptor

関連する問題