MyBatis使用单个映射器的多个数据源

时间:2014-12-09 12:17:59

标签: java guice mybatis

我正在使用guice来绑定和注入用于从不同数据库中删除条目的MyBatis映射器的系统。事实是所有数据库都位于不同的主机中,但具有相同的结构。由于它们很多并且主机的数量和位置经常发生变化,我想安装一个MyBatis模块,其中包含使用相同映射器动态加载的不同数据源。

我一直在四处寻找,但无法弄清楚如何解决映射器模糊问题。我还看了一下MyBatis beans CDI插件,它可以更容易地添加带有多个数据源的命名映射器,但仍然无法使其工作,因为我没有固定的数据源列表,我可以命名。

我错过了实现这一目标的简单方法吗?

3 个答案:

答案 0 :(得分:1)

您需要私下绑定MyBatisModule并使用唯一绑定属性公开映射。我在下面有一个例子。我已经证实它也有效:)

DaoModule :此模块设置为将单个映射器绑定到具有特定数据源的密钥。请注意,此类正在扩展“PrivateModue”,并且它将密钥公开给父模块。您将使用此密钥注入映射。

public class DaoModule<T> extends PrivateModule {

    private static final String ENVIRONMENT_ID = "development";

    private final Key<T> key;
    private final Class<T> mapper;
    private final Provider<DataSource> dataSourceProvider;

    public DaoModule(Key<T> key, Class<T> mapper, Provider<DataSource> dataSourceProvider) {
        this.key = key;
        this.mapper = mapper;
        this.dataSourceProvider = dataSourceProvider;
    }

    @Override
    protected void configure() {
        install(new InnerMyBatisModule());
        expose(key);
    }

    private class InnerMyBatisModule extends MyBatisModule {
        @Override
        protected void initialize() {
            bind(key).to(mapper);
            addMapperClass(mapper);

            environmentId(ENVIRONMENT_ID);
            bindDataSourceProvider(dataSourceProvider);
            bindTransactionFactoryType(JdbcTransactionFactory.class);
        }
    }
}

MyModule:此模块通过两个不同的密钥和不同的数据源安装两个具有相同映射器类型的DaoModule。

public class MyModule extends AbstractModule {

    @Override
    protected void configure() {
        Key<MapperDao> key1 = Key.get(MapperDao.class, Names.named("Mapper1"));
        Provider<DataSource> datasource1 = null;

        Key<MapperDao> key2 = Key.get(MapperDao.class, Names.named("Mapper2"));
        Provider<DataSource> datasource2 = null;

        install(new DaoModule<MapperDao>(key1, MapperDao.class, datasource1));
        install(new DaoModule<MapperDao>(key2, MapperDao.class, datasource2));
    }
}

Main:主要获取相同类型但具有不同数据源的两个映射器。

public class Main {
    public static void main(String... args) {
        Injector i = Guice.createInjector(new MyModule());

        MapperDao mapper1 = i.getInstance(Key.get(MapperDao.class, Names.named("Mapper1")));
        MapperDao mapper2 = i.getInstance(Key.get(MapperDao.class, Names.named("Mapper2")));
    }
}

示例注入类:这显示了如何使用字段注入来注入映射器

public class MyExampleClass {

   @Inject
   @Named("Mapper1")
   MapperDao mapper1;

   @Inject
   @Named("Mapper2")
   MapperDao mapper2;

}

答案 1 :(得分:1)

这个答案的范围与问题略有不同。对于拥有固定数量的数据源且需要共享映射器的任何人,还有一种解决方案,而不是按照接受的答案中描述的方式使用@Named

您只需使用

即可
interface SomeMapperForDbA extends SomeMapper {}

并在相应的SomeMapperForDbA中添加+公开PrivateModule

此处的接口名称充当逻辑数据源鉴别器,而所有映射查询stil在SomeMapper中的一个位置保持不变。这种方法与命名注入相比有利有弊,但它可以为某些人节省时间。

显然,您需要注入SomeMapperForDbA才能使用DbA数据源。也就是说,它只能在构造函数中完成,而实际代码中使用的类成员类型可以只是SomeMapper以避免混淆。

或者,您可以向SomeMapperForDbA添加一些特定于DbA的选择,如果数据库具有共同和不同的部分等。在这种情况下,我会建议一个更好的名称,这反映了这种逻辑。

即。不要害怕在需要时扩展映射器接口。

答案 2 :(得分:0)

org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource为此目的而设计。

https://www.baeldung.com/spring-abstract-routing-data-source