2016-08-10 5 views
0

injizieren wir erstellen eine Anwendung, wo wir Entity Updates in History Tabelle protokollieren müssen. Ich versuche, dies durch den Ruhezustand-Interzeptor zu erreichen, und wir könnten in der Lage sein, alle Änderungen zu bekommen, aber Schwierigkeiten beim Einfügen in die Audit-Tabelle.Wie spring repo in den Winterschlaf Interceptor

Meine JPA Konfiguration

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; 
} 

Mein Interceptor

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

}

in Verfahren afterTransactionCompletion Ich brauche alle -abschlussprüfungsgesellschaften in DB zu schreiben, ist der Frühling Autowire nicht, da diese Arbeit nicht geschafft Bean, gibt es eine Möglichkeit, DB-Sitzung in dieser Methode zu bekommen, so dass ich Einsätze durchführen kann.

Antwort

1

Die typische Lösung für die Injektion von Spring Beans in die nicht federgeführte Klasse ist statische Ressource Inhaber. Zum Beispiel haben Sie eine Klasse namens StaticServiceHolder und Annotate ist mit @Component dann statische Felder für die Spring Bean, die Sie durch Setter injizieren wollen. Wie:

@Component 
public class StaticServiceHolder 
{ 
    public static AuditService auditService; 

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

oder sogar einfacher, wenn Sie eine Menge von diesen Sachen haben müssen injiziert werden, dann können Sie die ApplicationContext Autowire. Auf diese Weise können Sie jede Bohne erhalten, die Sie benötigen.

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

So oder so, sollten Sie in der Lage sein, Ihre Sachen in der DB so lange andauern wie der Service ist, dass Sie verwenden Transactional. Hoffe, diese Arbeit für dich.

Für Transaktionsmanager-Setup:

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

    return transactionManager; 
} 
+0

Vielen Dank für Ihre Antwort. Der zweite Ansatz mit Anwendungskontext funktioniert in meinem Fall nicht. Ich bin mir nicht sicher, was ich falsch mache .. Versuch mit der ersten Appraktion –

+0

Ich könnte Repo mit statischem Halter injizieren .. einige, wie Daten nicht in DB gespeichert werden. Ich habe meinen Frühling JPA Repo Transnational noch kein Glück .. irgendwelche Gedanken ..? –

+0

hmmm, das ist wirklich ein anderes Thema, denke ich. Es hängt mit Ihrer 'TransactionManager'-Konfiguration zusammen. lass mich versuchen, dir zu helfen .... Ich habe die Antwort am Ende für eine typische TransactionManger Java-Konfiguration aktualisiert. Solange eine Transaktion beginnt, sollte die Persistenz funktionieren. –

-1

Ich weiß, dass dies ein wenig zu spät, aber vielleicht nützlich für andere. Wenn Sie die Spring Bean anstelle des Klassennamens als Wert für "hibernate.ejb.interceptor" verwenden, übernimmt Hibernate die Spring Bean, anstatt eine neue Klasse zu instanziieren.

Mehr finden Sie hier: Autowired to hibernate Interceptor

Verwandte Themen