spring多数据源配置笔记

本文阐述使用多数据源的额场景,以及如何使用springboot的配置多数据源。

关于后者,主要是直接引用其它博文:https://blog.csdn.net/u012060033/article/details/123759694

如果不想了解不太必要知道的,建议查看 https://www.cnblogs.com/chen-msg/p/7485701.html

 

一、多数据源的使用场景

使用多数据源的原因一般有:

  1. 数据采集
  2. 分库
  3. 其它

本文主要讨论的是分库问题。现在讨论的一般所谓“分库”是主要因为两个目的:

  1. 实现多租户
  2. 数据的水平分割,以便增加数据吞吐能力
  3. 读写分离

实现多租户

在某些前提下,通过分库来实现多租户也是可以,例如不想浪费应用服务器的资源,减少维护的压力。

但这个行为,本人并不是很认可。因为当你的客户没有多少数据量的时候,分库分表其实没有太大意义。

如果客户的数据很多,那么客户应该给出更多的钱,这种情况下也没有必要和其它客户共享一个硬件资源。

至于业界一直鼓吹的SAAS,云之类的,大部分业务场景下,对于大公司并没有特别的吸引力。因为财大气粗,这个时候他们主要考虑一个问题:数据安全性。

大一点的公司也是这个思路。例如字节自己建立数据中心,也是类似的心思:安全,不想受制于人等等。

所以,现今国内大公司更多的做法是:自己采购服务器,自己组建it团队。和其它公司共享一个别的公司运营的云平台,把关键的商务数据放上去,不太可能的。

读写分离

这个建议直接使用数据库自身的功能了。但如果的确有某些不得不用的理由,也是可以的。

不过项目做多了,总是有一些特别的要求,所以本章节不再讨论要不要使用多数据源。

 

二、配置多数据源

2.1配置多数据源所需要面临的几个问题

  • 如果有ocrm等和数据源有关的组件,那么这些组件内部如何切换
  • 多个数据源之间的事务一致性如何处理(如果它们有关系的话)
  • 切换数据源的成本如何降低一些,即如何使用更少的资源和更少的计算能力来进行切换

如何保持事务一致性的话题内容太多,此处略过。

所以剩下的主要关心问题就是如何切换。

如果是mybatis或者mybatis-plus等orm还是相对友好的--因为是现成的。如果是自己编写的ocrm框架,那么需要稍微花费一些心思。

2.2一般的实现方式

spring本身支持多数据源的配置,所以难度上并没有什么。对于设计人员而言,主要工作是慎重选择实现的方式。

spring的方式步骤:

  1. 定义个数据源
  2. 定义数据源有关的bean对象:datasource,jdbcTemplate,事务管理器等等

其它变化都是基于以上基础实现的。

以下文章讲解的比较清楚:https://www.cnblogs.com/chen-msg/p/7485701.html

 

三、例子

例子上按照https://www.cnblogs.com/chen-msg/p/7485701.html来编写。

运行环境:windows11 ,mysql8.0.x,springboot 2.6.7

3.1 application.properties

spring.datasource.type=com.zaxxer.hikari.HikariDataSource
spring.datasource.hikari.autoCommit=false
spring.datasource.hikari.connectionTimeout=180000
spring.datasource.hikari.idleTimeout=600000
spring.datasource.hikari.maxLifetime=1800000
spring.datasource.hikari.minimumIdle=3
spring.datasource.hikari.maximumPoolSize=6
spring.datasource.hikari.connection-test-query=select 1

#多数据源演示
spring.datasource.school.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.school.jdbcUrl=jdbc:mysql://localhost:7799/spring?rewriteBatchedStatements=true&autoReconnect=true&allowMultiQueries=true&useSSL=false&allowPublicKeyRetrieval=true
spring.datasource.school.username=spring
spring.datasource.school.password=123

spring.datasource.factory.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.factory.jdbcUrl=jdbc:mysql://localhost:7799/factory?rewriteBatchedStatements=true&autoReconnect=true&allowMultiQueries=true&useSSL=false&allowPublicKeyRetrieval=true
spring.datasource.factory.username=spring
spring.datasource.factory.password=123

 

 

3.2 DataSourceConfig.java --配置数据源

package com.example.multids.config;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;


@Configuration
public class DataSourceConfig {
    @Bean(name = "factoryDataSource")
    @Qualifier("factoryDataSource")
    @Primary
    @ConfigurationProperties(prefix = "spring.datasource.factory")
    public DataSource factoryDataSource()
    {
        System.out.println("-------------------- factoryDataSource init ---------------------");
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "schoolDataSource")
    @Qualifier("schoolDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.school")
    public DataSource schoolDataSource()
    {
        System.out.println("-------------------- schoolDataSource init ---------------------");
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "schoolJdbcTemplate")
    @Qualifier("schoolJdbcTemplate")
    public JdbcTemplate schoolJdbcTemplate(@Qualifier("schoolDataSource") DataSource dataSource)
    {
        return new JdbcTemplate(dataSource);
    }

    @Bean(name = "factoryJdbcTemplate")
    @Qualifier("factoryJdbcTemplate")
    public JdbcTemplate factoryJdbcTemplate(@Qualifier("factoryDataSource") DataSource dataSource)
    {
        return new JdbcTemplate(dataSource);
    }
    
    /******配置事务管理********/
    
    @Bean
    public PlatformTransactionManager schoolTransactionManager(@Qualifier("schoolDataSource")DataSource ds) {
     return new DataSourceTransactionManager(ds);
    }
     
    @Bean
    public PlatformTransactionManager factoryTransactionManager(@Qualifier("factoryDataSource")DataSource ds) {
     return new DataSourceTransactionManager(ds);
    }
}

 

 

3.3 SqlController- 测试控制器

package com.example.multids.controller;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping(value = "/multids")
public class SqlController {

    @Qualifier("schoolJdbcTemplate")
    @Autowired
    private JdbcTemplate jdbcTp;

    @Qualifier("factoryJdbcTemplate")
    @Autowired
    private JdbcTemplate factoryJdbcTp;

    @RequestMapping(value = "getAll", method = { RequestMethod.GET, RequestMethod.POST })
    public Object getAll() {
        String sql = "select * from student limit 2";
        List<Map<String, Object>> studentList = jdbcTp.queryForList(sql);
        String inventorySql = "select * from inventory limit 2";
        List<Map<String, Object>> inventoryList = factoryJdbcTp.queryForList(inventorySql);
        Map<String, Object> result = new HashMap<>();
        result.put("student-spring-ds", studentList);
        result.put("inventory-factory-ds", inventoryList);
        return result;
    }
}

 

3.4 测试结果

浏览器执行结果:http://localhost:8081/multids/getAll

 

四、小结

总体而言,配置还是比较简单。

 

posted @ 2022-05-28 20:31  正在战斗中  阅读(925)  评论(0编辑  收藏  举报