Ho un'applicazione Spring Framework 4 che utilizza Hibernate 4.3.8 come provider JPA. Voglio usare i filtri Hibernate, e quindi ho bisogno di abilitarli. Voglio farlo a livello globale nell'applicazione, che sto cercando di fare con Spring AOP. L'idea è che posso scrivere un aspetto che abiliti i filtri ogni volta che una sessione viene creata/recuperata, come nella domanda this e this.Configurazione della sessione di sospensione con Spring AOP
Ho aggiunto le dipendenze spring-aop
e aspectjweaver
al mio progetto (utilizzando Maven). Ho aggiunto il seguente aspetto.
@Aspect
@Component
public class EnableHibernateFilters {
@Pointcut("execution(* org.hibernate.SessionFactory.getCurrentSession(..))")
protected void sessionBeingFetched() {
}
@AfterReturning(pointcut = "sessionBeingFetched()", returning = "object")
public void enableFilters(JoinPoint joinPoint, Object object) {
System.out.println("!!! Enabling filters !!!"); // Never printed
Session session = (Session) object;
session.enableFilter("myFilter");
}
}
Il mio problema è che i consigli di cui sopra (enableFilters
) non viene mai richiamato; né il testo è stampato, né il mio filtro è abilitato. Ho verificato che il mio aspetto viene rilevato e che AOP funziona nel mio progetto cambiando il pointcut in una delle mie classi. Ho anche provato a cambiare il pointcut a execution(* org.hibernate.SessionFactory.openSession(..))
, ma senza risultato.
Ho il sospetto che ciò sia causato da come ho configurato Hibernate, perché non configuro esplicitamente uno SessionFactory
; piuttosto, ho creato uno EntityManagerFactory
. Ecco la mia configurazione.
@Configuration
@EnableTransactionManagement
public class PersistenceConfig {
@Bean
public DataSource dataSource() throws NamingException {
Context ctx = new InitialContext();
return (DataSource) ctx.lookup("java:comp/env/jdbc/postgres"); // JNDI lookup
}
@Bean
public EntityManagerFactory entityManagerFactory() throws SQLException, NamingException {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setGenerateDdl(false);
vendorAdapter.setDatabase(Database.POSTGRESQL);
vendorAdapter.setShowSql(true);
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(vendorAdapter);
factory.setPackagesToScan(...);
factory.setDataSource(this.dataSource());
factory.afterPropertiesSet();
return factory.getObject();
}
@Bean
public JpaTransactionManager transactionManager() throws SQLException, NamingException {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(this.entityManagerFactory());
return transactionManager;
}
@Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
return new PersistenceExceptionTranslationPostProcessor();
}
}
Fondamentalmente non sono sicuro di quale collegamento utilizzare con la configurazione di cui sopra. Ho provato a scherzare con LocalContainerEntityManagerFactoryBean.setLoadTimeWeaver()
, ma non riuscivo a capirlo. Non so se ho anche bisogno di configurarlo comunque.
In sostanza, il mio setup AOP funziona per le mie classi personalizzate. Suppongo che il problema sia che la tessitura non è configurata con Hibernate o qualcosa del genere (non ho molta familiarità con questa parte di tutto questo) o che la sessione non è ottenuta attraverso il metodo SessionFactory.getCurrentSession()
a causa della mia configurazione. Ho provato a verificare che il mio consiglio abbia funzionato anche con Hibernate cambiando il mio pointcut su execution(* org.hibernate.Hibernate.isInitialized(..))
e invocando manualmente Hibernate.isInitialized(null)
nel mio codice, ma questo non ha attivato neanche il consiglio, quindi questo potrebbe essere il problema. Ho provato ciò che è stato suggerito in this post to enable Hibernate weaving, ma non ho potuto farlo fare alcuna differenza.
Ho anche provato a impostare il mio collegamento a execution(* org.springframework.orm.hibernate4.SessionHolder.getSession(..))
e execution(* org.springframework.orm.jpa.vendor.HibernateJpaDialect.getSession(..))
, ma anche senza fortuna.
Quindi, non sono sicuro di dove andare dopo. Come posso ottenere una sospensione dell'oggettodi Hibernate dal mio consiglio in modo da poter abilitare i filtri Hibernate? Grazie in anticipo!
EDIT: Solo nel caso, io ho @EnableAspectJAutoProxy
presente nella mia configurazione:
@Configuration
@ComponentScan(basePackages = { ... })
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class AppConfig {
// ...
}
Forse un '@ComponentScan (" org.hibernate ")' aiuta? – Ruben
@Ruben No, non fa differenza. – Andy0708
Si sta intercettando il 'SessioNFactory', ma si sta usando un semplice JPA (con hibernate come implementatore). Ovviamente questo non inizierà mai, non c'è 'SessionFactory' nella tua configurazione e quindi il tuo aspetto non combacia con niente. Scrivi invece il punto tagliato per "EntityManagerFactory.getEntityManager". –