简体   繁体   中英

How to use spring transaction manager in case of dynamic data source?

I have a scenario where datasource are dynamically created using Datasource Factory . So depending upon who accesses the system, DatasourceFacory(custom datasource factory) returns a corresponding datasource .

Now, with this strategy, how do I maintain Spring Transaction? Using a @Transactional annotation needs a fixed datasource with transaction manager configured.

I would like to continue to use @Transactional in a service method and not worry about having to maintain transaction myself.

I would think that I would have to extend some spring class and inject the datasource when the system starts.

I am using Spring and JdbcTemplate in my project. No Hibernate. Any help would be appreciated.

You have to use AbstractRoutingDataSource to link it with your transaction manager, this kind of datasource allows you use different datasources choosing them in runtime.

After that spring handles the transaction properly. You can check this kind of DataSource in the Spring Documentation.

The other option is has different transactionManagers.

For no-xml lovers

@Bean(name = "mysqldatasource1")
public DataSource dataSource() {
    BasicDataSource dataSource = new BasicDataSource();
    dataSource.setDriverClassName(classname);
    dataSource.setUrl(url);
    dataSource.setUsername(usernmae);
    dataSource.setPassword(password);
    return dataSource;
}

@Bean(name = "mySqlJdbcTemplate1")
public JdbcTemplate jdbcTemplate() {
    JdbcTemplate jdbcTemplate = new JdbcTemplate();
    jdbcTemplate.setDataSource(dataSource());
    return jdbcTemplate;
}

@Bean(name="mysqlTransaction1") 
@Autowired
DataSourceTransactionManager tm1(@Qualifier ("mysqldatasource") DataSource datasource) {
    DataSourceTransactionManager txm  = new DataSourceTransactionManager(datasource);
    return txm;
}
@Bean(name = "mysqldatasource2")
public DataSource dataSource() {
    BasicDataSource dataSource = new BasicDataSource();
    dataSource.setDriverClassName(classname);
    dataSource.setUrl(url);
    dataSource.setUsername(usernmae);
    dataSource.setPassword(password);
    return dataSource;
}

@Bean(name = "mySqlJdbcTemplate2")
public JdbcTemplate jdbcTemplate() {
    JdbcTemplate jdbcTemplate = new JdbcTemplate();
    jdbcTemplate.setDataSource(dataSource());
    return jdbcTemplate;
}

@Bean(name="mysqlTransaction2") 
@Autowired
DataSourceTransactionManager tm1(@Qualifier ("mysqldatasource2") DataSource datasource) {
    DataSourceTransactionManager txm  = new DataSourceTransactionManager(datasource);
    return txm;
}

You can create multiple Transaction Managers with different datasources and then access them in @Transactional annotation as follows:

 <bean id="txManager1" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource1"/>
    <qualifier value="txManager1"/>
 </bean>

Access it as:

 @Transactional("txManager1")

Similarly,

 <bean id="txManager2" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource2"/>
    <qualifier value="txManager2"/>
 </bean>

Access it as:

 @Transactional("txManager2")

As there can be only one annotation-driven TxManager, do not forget to remove this:

<tx:annotation-driven transaction-manager="transactionManager" />

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM