2014-12-09 109 views
1

我正在使用guice綁定和注入MyBatis映射器的系統,該映射器用於從不同的數據庫中刪除條目。事實是,所有數據庫都位於不同的主機中,但具有相同的結構。由於它們有很多,主機的數量和位置經常發生變化,我想安裝一個MyBatis模塊,其中包含使用相同映射器動態加載的不同數據源。MyBatis使用單個映射器的多個數據源

我一直在環顧四周,但無法弄清楚如何解決映射模糊。我還研究了MyBatis beans CDI插件,這使得添加具有多個數據源的命名映射器變得更加容易,但仍然無法使其工作,因爲我沒有可以命名的固定數據源列表。

我錯過了一個簡單的方法來實現這一目標嗎?

回答

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的:該模塊由兩個不同的密鑰和不同的數據源的安裝兩個DaoModules用相同的映射器類型。

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)); 
    } 
} 

主:和主獲取相同類型的兩個映射器,但具有不同的數據源。

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; 

} 
+0

如果你喜歡這個答案,請把它標記爲這樣。 – 2014-12-10 17:31:38

+0

謝謝,這真的很有幫助。我正在研究的背景有點複雜,並且在某一時刻,實際上在那裏注射器變得有點困難。這就是爲什麼我試圖使用MapBinder與我的所有映射器而不是鍵綁定。這樣,我可以檢索所有映射器而不需要噴射器對象本身,但它不起作用。你知道是否有可能做到這一點,或者是唯一選擇的關鍵綁定?再次感謝 – 2015-01-08 15:57:19

+0

@AndreuMarimon你不需要使用注入器......只需要在將值注入類時使用「@Named」註釋。我已將MyExampleClass添加到答案中。我只是用注射器來證明它被綁定在guice中。 – 2015-01-09 21:10:15

1

此答案爲稍微不同的範圍比的問題。對於任何擁有固定數量的數據源並且需要共享映射器的人員,還有一種解決方案,而不使用@Named這種方式在接受的答案中進行描述。

您可以簡單地使用

interface SomeMapperForDbA extends SomeMapper {} 

,並在相應PrivateModule添加+揭露SomeMapperForDbA

此處的接口名稱充當邏輯數據源鑑別器,而所有映射查詢stil保持完好無損,位於SomeMapper的一個位置。這種方法對命名注入有利有弊,但它起作用並可能爲一些人節省一天的時間。

顯然,您需要注入SomeMapperForDbA才能使用DbA數據源。也就是說,它只能在構造函數中完成,而實際代碼中使用的類成員類型只能是SomeMapper以避免混淆。

另外,如果數據庫有共同的和不同的部分等,你可以添加一些特定於DbA的選擇到SomeMapperForDbA。在這種情況下,我會建議一個更好的名稱,這反映了這樣的邏輯。

I.e.在需要時不要害怕擴展映射器接口。