I have two transaction managers configured in annotation-based configuration class:
@Configuration
@EnableTransactionManagement
public class DBConfig implements TransactionManagementConfigurer {
//...
@Override
public PlatformTransactionManager annotationDrivenTransactionManager() {
return defTransactionManager();
}
@Bean
@Qualifier("defSessionFactory")
public LocalSessionFactoryBean defSessionFactory() {
LocalSessionFactoryBean sfb = new LocalSessionFactoryBean();
sfb.setDataSource(defDataSource());
Properties props = new Properties();
//...
sfb.setHibernateProperties(props);
sfb.setPackagesToScan("my.package");
return sfb;
}
@Bean
@Qualifier("defTransactionManager")
public PlatformTransactionManager defTransactionManager() {
return new HibernateTransactionManager(defSessionFactory().getObject());
}
@Bean
@Qualifier("secondSessionFactory")
public LocalSessionFactoryBean secondSessionFactory() {
LocalSessionFactoryBean sfb = new LocalSessionFactoryBean();
sfb.setDataSource(secondDataSource());
Properties props = new Properties();
//...
sfb.setHibernateProperties(props);
sfb.setPackagesToScan("my.package.subpackage");
return sfb;
}
@Bean
@Qualifier("secondTM")
public PlatformTransactionManager secondTransactionManager() {
return new HibernateTransactionManager(secondSessionFactory().getObject());
}
}
My intention is use annotation transactions with two transaction managers. Methonds annotated like this
@Transactional
public void method() {}
should be handled by defTransactionManager
And methods annotated like this
@Transactional("secondTM")
public void anotherMethod() {}
by secondTransactionManager
defTransactionManager works fine but when it comes to anotherMethod() I get:
org.hibernate.HibernateException: No Session found for current thread
When I use programmatic transaction management for anotherMethod (autowire secondSessionFactory, use TransactionTemplate) everything works fine.
In case of @EnableTranscationManagement Spring will use by-type lookup, you can provide your own lookup method to a single transaction manager, but it will not work for two tx managers
If you want to check how Spring determines the transaction to execute, you can try to debug the TransactionAspectSupport class. The key methods are setTransactionManagerBeanName
and determineTransactionManager
.
Just in case anyone runs into this problem, I found a solution:
@Configuration
@EnableTransactionManagement
@DependsOn("myTxManager")
@ImportResource("classpath:applicationContext.xml")
public class AppConfig implements TransactionManagementConfigurer {
@Autowired
private PlatformTransactionManager myTxManager;
...
@Override
public PlatformTransactionManager annotationDrivenTransactionManager() {
return this.myTxManager;
}
In this way, you can use a specific txManager defined in an xml configuration.
In case you want to define the txManager used on service-level, you shall remove the @EnableTransactionManagement
annotation from the @Configuration
class and specify the txManager in the @Transactional
annotations, e.g.
@Service
@Transactional(value="myTxManager", readOnly = true)
public class MyServiceImpl implements MyService { ... }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With