2016-08-10 2 views
0

мы создаем одно приложение, в котором нам нужно регистрировать обновления Entity в таблице History. Я пытаюсь достичь этого с помощью перехватчика спящего режима, и мы смогли бы добиться всех изменений, но с трудностями в их вставке в таблицу аудита.Как добавить весеннее репо в перехватчик гибернации

Моя конфигурация 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>(); 
     } 
    } 
    } 

}

в методе afterTransactionCompletion мне нужно написать все аудиторские объекты в БД, Autowire не работает, так как это не пружинные удалось bean, есть ли способ получить сеанс DB в этом методе, чтобы я мог выполнять вставки.?

ответ

1

Типичное решение для впрыскивания весенних бобы в класс, не связанный с пружиной, составляет статический держатель ресурсов. Например, у вас есть класс StaticServiceHolder, а аннотация - с @Component, затем создайте статические поля для весеннего компонента, который вы хотите ввести через setter. Как:

@Component 
public class StaticServiceHolder 
{ 
    public static AuditService auditService; 

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

или даже проще, если у вас есть много этих вещей нужно вводить, то вы можете Autowire в 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(); 

В любом случае, вы должны быть в состоянии сохраняться ваши вещи в БД до тех пор, как сервис, который вы используете Transactional. Надеюсь, эта работа для вас.

Для менеджера установки сделки:

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

    return transactionManager; 
} 
+0

Спасибо за ваш ответ. Второй подход с контекстом приложения не работает в моем случае .. не знаю, что я там делаю. Попытка с первой оценкой –

+0

Я мог бы вставить репо с помощью статического держателя .. некоторые, как данные не сохраняются в БД. Я сделал свою весеннюю ретрансляцию JPA транснациональной, еще не повезло .. какие-то мысли ..? –

+0

hmmm, это действительно другая тема, я думаю. Это связано с настройкой «TransactionManager». позвольте мне попытаться помочь вам .... Я обновил ответ в конце для типичной конфигурации java TransactionManger. Пока начинается транзакция, упор должен работать. –

-1

Я знаю, что это немного поздно, но может быть полезным для других. При использовании весеннего боба вместо имени класса в качестве значения для "hibernate.ejb.interceptor", hibernate берет весенний боб вместо создания нового класса.

Больше найти здесь: Autowired to hibernate Interceptor

Смежные вопросы