SpringとMyBatisを使ってデータベースが作成された契機でコネクションを発行したい

# したいこと
 - 各サーバにMySQLがあり、アプリからそれぞれにアクセスする
  - static_db（10.0.0.101:3306）
     - アプリ起動時にコネクションをプールしておく
  - dynamic_db（10.0.0.111:3306 ～ 10.0.0.115:3306）
     - dynamic_dbはアプリ起動時にはまだ作成されていない
     - **作成された契機で接続するデータベースを決めて**、コネクションを発行したい

# 実現方法
 - static_dbは普通にXML設定ファイル（spring-servlet.xml）を使用する
 - dynamic_dbはXML設定ファイルを使用**せずに**、SqlSessionFactoryを動的に生成する
  - [How do I build SqlSessionFactory without XML?](https://kodejava.org/how-do-i-build-sqlsessionfactory-without-xml/)

# 実装

## 各種バージョン
 - Java 1.8
 - Spring 4.2.4.RELEASE
 - MyBatis 3.2.2
 - MyBatis-Spring 1.2.1
 - MySQL 5.6.39

## static_dbの接続情報の設定

```xml:spring-servlet.xml
  <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    <property name="url" value="jdbc:mysql://10.0.0.101:3306/static_db" />
    <property name="username" value="root" />
    <property name="password" value="password" />
  </bean>

  <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="basePackage" value="sample.da.mapper" />
    <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
  </bean>

  <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean" name="sqlSessionFactory">
    <property name="dataSource" ref="dataSource"></property>
    <property name="mapperLocations" value="classpath*:sample/da/mapper/*.xml"/>
  </bean>

  <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/>
  </bean>
  <tx:annotation-driven transaction-manager="transactionManager"/>
```

## static_dbへのアクセス
DIされたMapperインスタンスを使用

```java
@Service
public class StaticDb01AccessService {

	@Autowired
	private UsersMapper usersMapper;
	
	public void insert() {
		Users record = new Users();
		record.setNum("001");
		record.setName("田中一郎");
		record.setCreated(new Date());
		record.setUpdated(new Date());
		usersMapper.insert(record);
	}
}
```
## dynamic_dbへのアクセス
手動でSqlSessionFactoryやMapperを生成

```java
@Service
public class DynamicDbAccessService {

	// 例えば、10.0.0.115のdynamic_dbが作成された契機で呼ばれた
	public void insert(String endpoint) throws Exception {
		DataSource dataSource = getDataSource(endpoint); // endpoint「10.0.0.115」
		
		TransactionFactory trxFactory = new JdbcTransactionFactory();
		
		Environment env = new Environment("dynamic_db", trxFactory, dataSource);
		
		Configuration config = new Configuration(env);
		TypeAliasRegistry aliases = config.getTypeAliasRegistry();
		aliases.registerAlias("user", Users.class);
		
		config.addMapper(UsersMapper.class);
		
		SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(config);
		SqlSession session = factory.openSession();
		
		try {
			UsersMapper usersMapper = session.getMapper(UsersMapper.class);
			
			Users record = new Users();
			record.setNum("001");
			record.setName("田中一郎");
			record.setCreated(new Date());
			record.setUpdated(new Date());
			
			usersMapper.insert(record);
			
			session.commit();
		} catch (Exception e) {
			session.rollback();
		} finally {
			session.close();
		}
	}

	private DataSource getDataSource(String endpoint) {
		BasicDataSource dataSource = new BasicDataSource();
		dataSource.setDriverClassName("com.mysql.jdbc.Driver");
		dataSource.setUrl(String.format("jdbc:mysql://%s/dynamic_db", endpoint));
		dataSource.setUsername("root");
		dataSource.setPassword("password");
		return dataSource;
	}
}
```