Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple transaction managers annotation configuration

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.

like image 693
Alexander Camperov Avatar asked Nov 04 '22 18:11

Alexander Camperov


2 Answers

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.

like image 71
Boris Treukhov Avatar answered Nov 09 '22 12:11

Boris Treukhov


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 { ... }
like image 43
Sleeper9 Avatar answered Nov 09 '22 14:11

Sleeper9