Skip to content

多数据源

日常开发,多数据源场景,避免不了,AutoTable内部支持多数据源,提供了自定义数据源的切换接口,使用者根据不同数据源框架自行切换。

spring boot应用

假设在Entity上通过@DS(value:String)注解来标注不同的数据源,其中value是数据源的名称。 DynamicDataSourceContextHolder类是动态数据源框架的全局数据源控制类

java
// spring boot应用,直接使用@Component注入即可
@Component
public class MyDataSourceHandler implements IDataSourceHandler {

    /**
     * 根据实体类获取对应的数据源名称
     * @param clazz 实体类
     */
    @Override
    public String getDataSourceName(Class<?> clazz) {
        // 假定自定义的多数据源,有一个注解Ds,通过在类上标注Ds注解来指定类的数据源。*其他方式大同小异,此处仅举例说明。
        Ds ds = clazz.getAnnotation(Ds.class);
        if (ds != null) {
            return ds.value();
        } else {
            return DynamicDataSourceContextHolder.getContextKey();
        }
    }

    /**
     * 根据数据源名称,切换数据源
     * @param dataSourceName 来自getDataSourceName的返回值
     */
    @Override
    public void useDataSource(String dataSourceName) {
        DynamicDataSourceContextHolder.setContextKey(dataSourceName);
    }

    /**
     * 根据数据源名称,清除数据源
     * @param dataSourceName 来自getDataSourceName的返回值
     */
    @Override
    public void clearDataSource(String dataSourceName) {
        DynamicDataSourceContextHolder.removeContextKey();
    }
}

普通java应用

普通java应用的实现方式相较于有所不同,但是主要取决于如何实现,因为AutoTable内部是通过SqlSessionFactory 来确定数据源的,所以,普通java应用需要手动切换SqlSessionFactory

java
public class DynamicDataSourceHandler implements IDataSourceHandler {

    private static final Map<String, String> CONFIG_MAP = new HashMap<String, String>() {{
        put("mysql", "mybatis-config.xml");
        put("pgsql", "mybatis-config-pgsql.xml");
        put("sqlite", "mybatis-config-sqlite.xml");
    }};
    private static final Map<String, SqlSessionFactory> STRING_SQL_SESSION_FACTORY_MAP = new HashMap<>();

    @Override
    public void useDataSource(String dataSourceName) {

        SqlSessionFactory sqlSessionFactory = STRING_SQL_SESSION_FACTORY_MAP.computeIfAbsent(dataSourceName, $ -> {

            String resource = CONFIG_MAP.get(dataSourceName);

            try (InputStream inputStream = TestApplication.class.getClassLoader().getResourceAsStream(resource)) {
                // 使用SqlSessionFactoryBuilder加载配置文件
                return new SqlSessionFactoryBuilder().build(inputStream);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        });

        // 设置新的SqlSessionFactory
        SqlSessionFactoryManager.setSqlSessionFactory(sqlSessionFactory);
    }

    @Override
    public void clearDataSource(String dataSourceName) {
        SqlSessionFactoryManager.cleanSqlSessionFactory();
    }

    @Override
    public @NonNull String getDataSourceName(Class<?> clazz) {
        Ds annotation = clazz.getAnnotation(Ds.class);
        if (annotation != null) {
            return annotation.value();
        }
        // 默认mysql
        return "mysql";
    }
}

提示

spring boot中不需要手动调用SqlSessionFactoryManager.setSqlSessionFactory,是因为spring boot保持了SqlSessionFactory 的单实例,通过切换内部的DataSource实现切换数据源,AutoTable的spring-boot-starter包,在初始化的时候就把spring管理的SqlSessionFactory 通过SqlSessionFactoryManager.setSqlSessionFactory配置到了框架中

第三方集成

如果你使用的是Mybatis-plus、Mybatis-flex等三方的开源框架,他们都有成熟的多数据源方案,AutoTable可以进行良好的集成,可参考第三方框架集成,内部均实现了相关框架的多数据方案