动态数据源路由 – 未初始化DataSource路由器

我指的是本文 ,我们可以使用Spring Framework中的AbstractRoutingDataSource动态更改应用程序使用的数据源。 我正在使用Mybatis(3.3.0)和Spring(4.1.6.RELEASE)。 如果从主数据库获取数据时发生exception,我想切换到备份数据库。 在这个例子中,我使用了hsql和mysql db。

RoutingDataSource

public class RoutingDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { return DataSourceContextHolder.getTargetDataSource(); } } 

DataSourceContextHolder

 public class DataSourceContextHolder { private static final ThreadLocal contextHolder = new ThreadLocal(); public static void setTargetDataSource(DataSourceEnum targetDataSource) { contextHolder.set(targetDataSource); } public static DataSourceEnum getTargetDataSource() { return (DataSourceEnum) contextHolder.get(); } public static void resetDefaultDataSource() { contextHolder.remove(); } } 

ApplicationDataConfig

 @Configuration @MapperScan(basePackages = "com.sample.mapper") @ComponentScan("com.sample.config") @PropertySource(value = {"classpath:app.properties"}, ignoreResourceNotFound = true) public class ApplicationDataConfig { @Bean public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer(); return configurer; } @Bean public SqlSessionFactoryBean sqlSessionFactoryBean() throws Exception { SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); RoutingDataSource routingDataSource = new RoutingDataSource(); routingDataSource.setDefaultTargetDataSource(dataSource1()); Map targetDataSource = new HashMap(); targetDataSource.put(DataSourceEnum.HSQL, dataSource1()); targetDataSource.put(DataSourceEnum.BACKUP, dataSource2()); routingDataSource.setTargetDataSources(targetDataSource); sessionFactory.setDataSource(routingDataSource); sessionFactory.setTypeAliasesPackage("com.sample.common.domain"); sessionFactory.setMapperLocations( new PathMatchingResourcePatternResolver() .getResources("classpath*:com/sample/mapper/**/*.xml")); return sessionFactory; } @Bean public DataSource dataSource1() { return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.HSQL).addScript( "classpath:database/app-hsqldb-schema.sql").addScript( "classpath:database/app-hsqldb-datascript.sql").build(); } @Bean public DataSource dataSource2() { PooledDataSourceFactory pooledDataSourceFactory = new PooledDataSourceFactory(); pooledDataSourceFactory.setProperties(jdbcProperties()); return pooledDataSourceFactory.getDataSource(); } @Bean protected Properties jdbcProperties() { //Get the data from properties file Properties jdbcProperties = new Properties(); jdbcProperties.setProperty("url", datasourceUrl); jdbcProperties.setProperty("driver", datasourceDriver); jdbcProperties.setProperty("username", datasourceUsername); jdbcProperties.setProperty("password", datasourcePassword); jdbcProperties.setProperty("poolMaximumIdleConnections", maxConnectionPoolSize); jdbcProperties.setProperty("poolMaximumActiveConnections", minConnectionPoolSize); return jdbcProperties; } } 

客户

  @Autowired private ApplicationMapper appMapper; public MyObject getObjectById(String Id) { MyObject myObj = null; try{ DataSourceContextHolder.setTargetDataSource(DataSourceEnum.HSQL); myObj = appMapper.getObjectById(Id); }catch(Throwable e){ DataSourceContextHolder.setTargetDataSource(DataSourceEnum.BACKUP); myObj = appMapper.getObjectById(Id); }finally{ DataSourceContextHolder.resetDefaultDataSource(); } return getObjectDetails(myObj); } 

我收到以下exception

 ### Error querying database. Cause: java.lang.IllegalArgumentException: DataSource router not initialized 

但是,如果我一次只使用一个数据库,那么我就可以正常工作,这意味着数据源配置没有问题。

你可以尝试这最后一行(按相同的顺序): –

 targetDataSource.put(DataSourceEnum.HSQL, dataSource1()); targetDataSource.put(DataSourceEnum.BACKUP, dataSource2()); routingDataSource.setTargetDataSources(targetDataSource); routingDataSource.afterPropertiesSet(); 

我遇到了同样的问题,并找到了使用Hibernate的SchemaExport类的解决方案。 对于每个DataSourceEnum,您可以手动初始化数据源。

这是我对自己的问题描述的详细答案