MyBatisによる動的データソース切り替え方法

MyBatis の動的データソース切り替えを実現するには、次の手順を実行します。

  1. 複数のデータソースを作成する場合は、まずSpringの設定ファイルで複数のデータソースの設定を行う必要があります。例えば、2つのデータソース、「dataSource1」と「dataSource2」の設定を行います。
  2. データソース切り替えの作成:実行時にデータソースを切り替えるデータソース切り替えを作成します。ThreadLocalやAOPなどの方法を使用して実装できます。
  3. MyBatisのSqlSessionFactoryの設定: MyBatisの設定ファイルで、複数のSqlSessionFactoryを設定し、それぞれ異なるデータソースを指定する。
  4. マッパインターフェースの作成: 各データソースに対応したマッパインターフェースを作成します。
  5. Mapper マッピングファイルを作成:各 Mapper インターフェースに対応する Mapper マッピングファイルを作成し、別々に異なるデータソースを指定。
  6. 動的データソースルーターの設定:異なる条件に基づいて適切なデータソースを選択するために、Spring 設定ファイルで動的データソースルーターを設定する。
  7. 動的データソースを使用:データソースを複数使用したい場合は、動的データソースルーターのメソッドを呼び出してデータソースを切り替えます。

以下に簡単なサンプルコードを示します。

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()メソッドを使用してデータソースを切り替えます。

bannerAds