如何連接兩個數(shù)據(jù)庫且進(jìn)行讀寫分離?

在開發(fā)中我們有可能會遇到一個項目需要配置多個數(shù)據(jù)源,或者需要讀寫分離的配置,在啟動類上貼上@MapperScan注解指定掃描對應(yīng)的mapper.xml文件肯迪那個是無法滿足了。我們可以通過自定義配置數(shù)據(jù)庫配置類來解決這個問題,方式有很多,不同的業(yè)務(wù)采用的方式也不同,下面我簡單的介紹我們項目的使用的方法

比如:項目中我需要連接opretion和device這個兩個數(shù)據(jù)庫,且需要進(jìn)行讀寫分離,在配置文件中如下:

image.png

針對device庫我們先創(chuàng)建一個數(shù)據(jù)庫連接配置類

@Configuration
@MapperScan(basePackages = {"com.liuqing.my.repo.device"}, sqlSessionTemplateRef = "deviceSqlSessionTemplate")  
public class DeviceDSConfig {

    @Value("${props.sql.show}")  //定義在配置文件中的字段 ture
    private String sqlShow;
}
  • @MapperScan

    • basePackages = {"com.liuqing.my.repo.device"}

      指定包掃描

    • sqlSessionTemplateRef = "deviceSqlSessionTemplate")

      指定sqlSessionTemplateRef

在類中添加配置文件中的讀寫數(shù)據(jù)源

@ConfigurationProperties(prefix = "spring.shardingsphere.datasource.device.read")
    public DataSource deviceReadDataSource() {
        return new DruidDataSource();
    }
    @Bean
    @ConfigurationProperties(prefix = "spring.shardingsphere.datasource.device.write")
    public DataSource deviceWriteDataSource() {
        return new DruidDataSource();
    }

@ConfigurationProperties注解的作用和@Value類似,都是獲取配置文件中相應(yīng)的配置值,但是@ConfigurationProperties與@Value不同的是,@Value一次只能獲取一個值,但是@ConfigurationProperties可以獲取多個值,此處可以將配置文件中的屬性,自動封裝到DruidDataSource的屬性中

配置Sharding數(shù)據(jù)源的Bean,也就是device.readdevice.write讀寫分離的數(shù)據(jù)源

通過@Qualifier注解來指定我們想要使用 deviceReadDataSource 方法返回的 bean ,即獲取deviceReadDataSource方法返回DruidDataSource對象,deviceWriteDataSource同理。

通過LoadBalanceStrategyConfiguration是實現(xiàn)我們負(fù)載均衡策略

通過MasterSlaveRuleConfiguration構(gòu)造方法實現(xiàn)自定義的負(fù)載均衡算法

@Bean
public DataSource deviceShardingDataSource(@Qualifier("deviceReadDataSource") DataSource readDataSource,   //指定使用deviceReadDataSource的Bean返回的readDataSource對象
                                          @Qualifier("deviceWriteDataSource") DataSource writeDataSource) throws SQLException {
    Map<String, DataSource> dataSourceMap = new HashMap<>();

    dataSourceMap.put("device-read", readDataSource);
    dataSourceMap.put("device-write", writeDataSource);

    //Spring負(fù)載均衡自動配置類   LoadBalanceStrategyConfiguration
    LoadBalanceStrategyConfiguration loadBalanceStrategyConfiguration = new LoadBalanceStrategyConfiguration("round_robin");
    //負(fù)載均衡算法
    MasterSlaveRuleConfiguration masterSlaveRuleConfig =
            new MasterSlaveRuleConfiguration(
                    "device_read_write",
                    "device-write",
                    Lists.newArrayList("device-read"),
                    loadBalanceStrategyConfiguration);

    Properties properties = new Properties();
    properties.setProperty("sql.show", sqlShow);

    return MasterSlaveDataSourceFactory.createDataSource(dataSourceMap, masterSlaveRuleConfig, properties);   //返回一個DataSource
}

創(chuàng)建返回SqlSessionFactory的Bean

1、創(chuàng)建MybatisSqlSessionFactoryBean對象配置SqlSessionFactory;

2、創(chuàng)建MybatisConfiguration對象調(diào)用setMapUnderscoreToCamelCase方法,開啟mapUnderscoreToCamelCase配置駝峰轉(zhuǎn)換

3、創(chuàng)建GlobalConfig對象出傳入MybatisConfiguration對象設(shè)置關(guān)閉對應(yīng)banner(可以選擇不關(guān),但是利于查看日志和控制臺)

4、通過ResourcePatternResolver資源模式解析器,配置mapper.xml的文件路徑

@Bean
@Primary  //在同樣的DataSource中,首先使用被標(biāo)注的SqlSessionFactory
public SqlSessionFactory deviceSqlSessionFactory(@Qualifier("deviceShardingDataSource") DataSource shardingDataSource) {
    MybatisSqlSessionFactoryBean bean = new MybatisSqlSessionFactoryBean();
    bean.setDataSource(shardingDataSource);    //設(shè)置 MybatisSqlSessionFactory的數(shù)據(jù)源

    //MyBatis開啟mapUnderscoreToCamelCase配置駝峰轉(zhuǎn)換
    MybatisConfiguration configuration = new MybatisConfiguration();
    configuration.setMapUnderscoreToCamelCase(true);

    GlobalConfig globalConfig = GlobalConfigUtils.getGlobalConfig(configuration);
    globalConfig.setBanner(false);   //關(guān)閉Mybatis 加載的banner

    bean.setGlobalConfig(globalConfig);
    bean.setConfiguration(configuration);

    // 添加XML目錄
    ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); //資源模式解析器
    try {
        bean.setMapperLocations(resolver.getResources("classpath:mapper/device/**/*Mapper.xml"));  //設(shè)施設(shè)置mapper映射器位置
        return bean.getObject();  //返回一個SqlSessionFactory'po
    } catch (Exception e) {
        e.printStackTrace();
        throw new RuntimeException(e);
    }
}

題外話:默認(rèn)情況下,@Autowired 按類型裝配 Spring Bean。如果容器中有多個相同類型的 bean,則框架將拋出 NoUniqueBeanDefinitionException, 以提示有多個滿足條件的 bean 進(jìn)行自動裝配。程序無法正確做出判斷使用哪一個,所以會報錯,可以使用@Primary和@Qualifier注解類解決這類問題

  • 通過將 @Qualifier 注解與我們想要使用的特定 Spring bean 的名稱一起進(jìn)行裝配,Spring 框架就能從多個相同類型并滿足裝配要求的 bean 中找到我們想要的
  • @Primary 的解,可以用來發(fā)生依賴注入的歧義時決定要注入哪個 bean。當(dāng)存在多個相同類型的 bean 時,此注解定義了Bean的首選項。

簡單來說就是@Qualifier注解那多個Bean指定了我要那個Bean,而@Primary注解表示那個多個Bean,先選貼了@Primary注解的Bean

創(chuàng)建SqlSessionTemplate的Bean

方法名要與類名上@MapperScan注解中的sqlSessionTemplateRef屬性值一致;否者無法映射

SqlSessionTemplate是MyBatis-Spring的核心。這個類負(fù)責(zé)管理MyBatis的SqlSession,調(diào)用MyBatis的SQL方法,翻譯異常。SqlSessionTemplate是線程安全的,可以被多個DAO所共享使用。

@Bean
@Primary
public SqlSessionTemplate deviceSqlSessionTemplate(@Qualifier("deviceSqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
    return new SqlSessionTemplate(sqlSessionFactory);
}

創(chuàng)建DataSourceTransactionManager 事務(wù)管理器

@Bean
@Primary
public DataSourceTransactionManager deviceTransactionManager(@Qualifier("deviceShardingDataSource") DataSource shardingDataSource) {
    return new DataSourceTransactionManager(shardingDataSource);
}

到此,我們的配置基本結(jié)束,根據(jù)我們配置的mapper包掃描下創(chuàng)建對應(yīng)的mapper接口,

image.png

在resource目錄下根據(jù)我們在配置類中配置的路徑存放即可;

image.png

最后


注意:這是一個數(shù)據(jù)源的案例,當(dāng)是需要配置多個數(shù)據(jù)源的時候,流程是一樣的

1.在配置文件中配置數(shù)據(jù)庫連接數(shù)據(jù)

2.創(chuàng)建配置類

3.創(chuàng)建mapper接口和mapper.xml文件

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容