MyBatisによる動的データソース切り替え方法
MyBatis の動的データソース切り替えを実現するには、次の手順を実行します。
- 複数のデータソースを作成する場合は、まずSpringの設定ファイルで複数のデータソースの設定を行う必要があります。例えば、2つのデータソース、「dataSource1」と「dataSource2」の設定を行います。
- データソース切り替えの作成:実行時にデータソースを切り替えるデータソース切り替えを作成します。ThreadLocalやAOPなどの方法を使用して実装できます。
- MyBatisのSqlSessionFactoryの設定: MyBatisの設定ファイルで、複数のSqlSessionFactoryを設定し、それぞれ異なるデータソースを指定する。
- マッパインターフェースの作成: 各データソースに対応したマッパインターフェースを作成します。
- Mapper マッピングファイルを作成:各 Mapper インターフェースに対応する Mapper マッピングファイルを作成し、別々に異なるデータソースを指定。
- 動的データソースルーターの設定:異なる条件に基づいて適切なデータソースを選択するために、Spring 設定ファイルで動的データソースルーターを設定する。
- 動的データソースを使用:データソースを複数使用したい場合は、動的データソースルーターのメソッドを呼び出してデータソースを切り替えます。
以下に簡単なサンプルコードを示します。
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DataSourceContextHolder.getDataSource();
}
}
public class DataSourceContextHolder {
private static final ThreadLocal<String> dataSourceHolder = new ThreadLocal<>();
public static void setDataSource(String dataSource) {
dataSourceHolder.set(dataSource);
}
public static String getDataSource() {
return dataSourceHolder.get();
}
public static void clearDataSource() {
dataSourceHolder.remove();
}
}
@Configuration
public class DataSourceConfig {
@Bean
@Primary
@ConfigurationProperties("spring.datasource.datasource1")
public DataSource dataSource1() {
return DataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties("spring.datasource.datasource2")
public DataSource dataSource2() {
return DataSourceBuilder.create().build();
}
@Bean
public DynamicDataSource dynamicDataSource() {
DynamicDataSource dataSource = new DynamicDataSource();
Map<Object, Object> targetDataSources = new HashMap<>();
targetDataSources.put("dataSource1", dataSource1());
targetDataSources.put("dataSource2", dataSource2());
dataSource.setTargetDataSources(targetDataSources);
dataSource.setDefaultTargetDataSource(dataSource1());
return dataSource;
}
@Bean
public SqlSessionFactory sqlSessionFactory(DynamicDataSource dynamicDataSource) throws Exception {
SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
sessionFactory.setDataSource(dynamicDataSource);
return sessionFactory.getObject();
}
}
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataSource {
String value() default "dataSource1";
}
@Aspect
@Component
public class DataSourceAspect {
@Before("@annotation(dataSource)")
public void beforeSwitchDataSource(JoinPoint joinPoint, DataSource dataSource) {
DataSourceContextHolder.setDataSource(dataSource.value());
}
@After("@annotation(dataSource)")
public void afterSwitchDataSource(JoinPoint joinPoint, DataSource dataSource) {
DataSourceContextHolder.clearDataSource();
}
}
@Mapper
public interface UserMapper {
@DataSource("dataSource1")
List<User> getAllUsersFromDataSource1();
@DataSource("dataSource2")
List<User> getAllUsersFromDataSource2();
}
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
public List<User> getAllUsersFromDataSource1() {
return userMapper.getAllUsersFromDataSource1();
}
public List<User> getAllUsersFromDataSource2() {
return userMapper.getAllUsersFromDataSource2();
}
}
上記のコードでは、@Configurationアノテーションにより複数のデータソースが設定され、@Primaryアノテーションによりデフォルトのデータソースが指定されています。DynamicDataSourceクラスでは、AbstractRoutingDataSourceを使用して動的にデータソースを切り替えます。ThreadLocalを使用して、現在のスレッドのデータソース選択を格納します。DataSourceAspectクラスでは、AOPを使用してデータソースを切り替えます。UserMapperインタフェースでは、@DataSourceアノテーションを使用して、どのデータソースを使用するかを指定します。UserServiceクラスでは、UserMapperインタフェースのメソッドを呼び出してデータベースを操作します。最後に、データソースを切り替える必要がある場所では、DataSourceContextHolder.setDataSource()メソッドを使用してデータソースを切り替えます。