SpringBoot多数据源配置实战

方式一:实现DataSource接口

所需资源

  • Spring boot
  • Mybatis-plus
  • MySql 数据库

SpringBoot配置多数据源

在pom文件中引入依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.7.8</version>
    <relativePath/> <!-- lookup parent from repository -->
  </parent>
  <groupId>com.study</groupId>
  <artifactId>DataSourceDemo</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <name>DataSourceDemo</name>
  <description>Demo project for Spring Boot</description>
  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
      <groupId>com.baomidou</groupId>
      <artifactId>mybatis-plus-boot-starter</artifactId>
      <version>3.5.1</version>
    </dependency>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>8.0.27</version>
      <scope>runtime</scope>
    </dependency>
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <optional>true</optional>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <configuration>
          <excludes>
            <exclude>
              <groupId>org.projectlombok</groupId>
              <artifactId>lombok</artifactId>
            </exclude>
          </excludes>
        </configuration>
      </plugin>
    </plugins>
  </build>

</project>

在properties文件中定义数据源所需的数据

spring.datasource.type=com.zaxxer.hikari.HikariDataSource

spring.datasource.db1.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.db1.jdbc-url=jdbc:mysql://localhost:3306/mbatis?useSSL=true&serverTimezone=Asia/Shanghai
spring.datasource.db1.username=root
spring.datasource.db1.password=root

spring.datasource.db2.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.db2.jdbc-url=jdbc:mysql://localhost:3306/test?useSSL=true&serverTimezone=Asia/Shanghai
spring.datasource.db2.username=root
spring.datasource.db2.password=root

mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
mybatis-plus.global-config.db-config.table-prefix=t_
mybatis-plus.global-config.db-config.id-type=auto

注意事项
各个版本的 springboot 配置 datasource 时参数有所变化,例如低版本配置数据库 url 时使用 url 属性,高版本使用 jdbc-url 属性,请注意区分。

定义多个数据源

@Configuration
public class DataSourceConfig {

    @Bean(name = "db1")
    @ConfigurationProperties(prefix = "spring.datasource.db1")
    public DataSource dataSource1(){
        HikariDataSource hikariDataSource = DataSourceBuilder.create().type(HikariDataSource.class).build();
        return hikariDataSource;
    }

    @Bean(name = "db2")
    @ConfigurationProperties(prefix = "spring.datasource.db2")
    public DataSource dataSource2(){
        HikariDataSource hikariDataSource = DataSourceBuilder.create().type(HikariDataSource.class).build();
        return hikariDataSource;
    }
}

@ConfigurationProperties注解用于将properties中指定的数据创建成指定的对象,但是,properties中的数据必须要与对象对象中的属性同名,不然无法由Spring Boot完成赋值。
由于我们要定义多个数据源,所以在Spring Boot数据源自动配置类中就无法确定导入哪个数据源来完成初始化,所以我们就需要禁用掉Spring Boot的数据源自动配置类,然后使用我们自定义的数据源配置类来完成数据源的初始化与管理。

@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
public class DataSourceDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DataSourceDemoApplication.class, args);
    }

}

在启动类上声明需要禁用的自动配置类:exclude ={DataSourceAutoConfiguration.class}

实现DataSource接口

缺点:产生大量的代码冗余,在代码中存在硬编码。

@Component
@Primary //@Primary注解 == @Order(1),用于设置此类的注入顺序
public class DynamicDataSource implements DataSource {
    //使用ThreadLocal而不是String,可以在多线程的时候保证数据的可靠性
    public static ThreadLocal<String> flag = new ThreadLocal<>();

    @Resource(name = "db1")
    private DataSource dataSource1; // 注入第一个数据源
    @Resource(name = "db2")
    private DataSource dataSource2; // 注入第二个数据源

    public DynamicDataSource(){ // 使用构造方法初始化ThreadLocal的值
        flag.set("r");
    }
    @Override
    public Connection getConnection() throws SQLException {
        // 通过修改ThreadLocal来修改数据源,
        // 为什么通过修改状态就能改变已经注入的数据源? 这就得看源码了。
        if(flag.get().equals("r")){
            return dataSource1.getConnection();
        }
        return dataSource2.getConnection();
    }

    @Override
    public Connection getConnection(String username, String password) throws SQLException {
        return null;
    }

    @Override
    public <T> T unwrap(Class<T> iface) throws SQLException {
        return null;
    }

    @Override
    public boolean isWrapperFor(Class<?> iface) throws SQLException {
        return false;
    }

    @Override
    public PrintWriter getLogWriter() throws SQLException {
        return null;
    }

    @Override
    public void setLogWriter(PrintWriter out) throws SQLException {

    }

    @Override
    public void setLoginTimeout(int seconds) throws SQLException {

    }

    @Override
    public int getLoginTimeout() throws SQLException {
        return 0;
    }

    @Override
    public Logger getParentLogger() throws SQLFeatureNotSupportedException {
        return null;
    }
}

实现DataSource接口我们本质上只使用了一个方法,就是getConnection()这个无参的方法,但是DataSource接口中所有的方法我们也都需要实现,只是不用写方法体而已,也就是存在了很多的 “废方法” 。
@Primary注解 == @Order(1),用于设置此类的注入顺序。

测试

@SpringBootTest
class DataSourceDemoApplicationTests {
    @Autowired
    private DeptService deptService;

    @Test
    void contextLoads() {
    }
    @Test
    public void test01(){
        DynamicDataSource.flag.set("r");
        List<Dept> depts1 = deptService.list();
        System.out.println(depts1);
        DynamicDataSource.flag.set("w");
        List<Dept> depts2 = deptService.list();
        System.out.println(depts2);
    }
}

方式二:继承AbstractRoutingDataSource类

减少了代码的冗余,但是还是会存在硬编码。

所需资源(同方式一)

SpringBoot配置多数据源(同方式一)

继承AbstractRoutingDataSource类

@Component
@Primary //@Primary注解 == @Order(1),用于设置此类的注入顺序
public class DynamicDataSource extends AbstractRoutingDataSource {
    //使用ThreadLocal而不是String,可以在多线程的时候保证数据的可靠性
    public static ThreadLocal<String> flag = new ThreadLocal<>();

    @Resource(name = "db1")
    private DataSource dataSource1; // 注入第一个数据源
    @Resource(name = "db2")
    private DataSource dataSource2; // 注入第二个数据源

    public DynamicDataSource(){ // 使用构造方法初始化ThreadLocal的值
        flag.set("r");
    }
    @Override
    protected Object determineCurrentLookupKey() {
        return flag.get(); // 通过key获取数据源
    }
    @Override
    public void afterPropertiesSet() {
        Map<Object,Object> targetDataSource = new ConcurrentHashMap<>();
        targetDataSource.put("r",dataSource1);
        // 将第一个数据源设置为默认的数据源。
        super.setDefaultTargetDataSource(dataSource1);
        targetDataSource.put("w",dataSource2);
        // 将Map对象赋值给AbstrictRoutingDataSource内部的Map对象中。
        super.setTargetDataSources(targetDataSource);
        super.afterPropertiesSet();
    }
}

AbstrictRoutingDataSource的本质就是利用一个Map将数据源存储起来,然后通过Key来得到Value来修改数据源。

测试

@SpringBootTest
class AbstractRoutingDataSourceDemoApplicationTests {

    @Autowired
    private DeptService deptService;

    @Test
    void contextLoads() {
    }
    @Test
    public void test01(){
        DynamicDataSource.flag.set("r");
        List<Dept> depts1 = deptService.list();
        System.out.println(depts1);
        DynamicDataSource.flag.set("w");
        List<Dept> depts2 = deptService.list();
        System.out.println(depts2);
    }
}

方式三:使用Spring AOP+自定义注解的形式

Spring AOP + 自定义注解的形式是一种推荐的写法,减少代码的冗余且不存在硬编码。
此方法适合对指定功能操作指定数据库的模式。

所需资源(同方式一)

SpringBoot配置多数据源(同方式一)

导入依赖

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

开启AOP支持

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
@EnableAspectJAutoProxy //开启Spring Boot对AOP的支持
public class AopDataSourceDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(AopDataSourceDemoApplication.class, args);
    }

}

定义枚举标识数据源

public enum DataSourceType {
    DB1,
    DB2
}
  1. 继承AbstractRoutingDataSource类
@Component
@Primary //@Primary注解 == @Order(1),用于设置此类的注入顺序
public class DynamicDataSource extends AbstractRoutingDataSource {
    //使用ThreadLocal而不是String,可以在多线程的时候保证数据的可靠性
    public static ThreadLocal<String> flag = new ThreadLocal<>();

    @Resource(name = "db1")
    private DataSource dataSource1; // 注入第一个数据源
    @Resource(name = "db2")
    private DataSource dataSource2; // 注入第二个数据源

    public DynamicDataSource(){ // 使用构造方法初始化ThreadLocal的值
        flag.set(DataSourceType.DB1.name());
    }

    @Override
    protected Object determineCurrentLookupKey() {
        return flag.get();
    }

    @Override
    public void afterPropertiesSet() {
        Map<Object,Object> targetDataSource = new ConcurrentHashMap<>();
        targetDataSource.put(DataSourceType.DB1.name(),dataSource1);
        targetDataSource.put(DataSourceType.DB2.name(),dataSource2);
        // 将第一个数据源设置为默认的数据源。
        super.setDefaultTargetDataSource(dataSource1);
        // 将Map对象赋值给AbstrictRoutingDataSource内部的Map对象中。
        super.setTargetDataSources(targetDataSource);
        super.afterPropertiesSet();
    }
}

自定义注解

@Target({ElementType.TYPE, ElementType.METHOD}) //限制在类和方法上
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface TargetDataSource {
    DataSourceType value() default DataSourceType.DB1;
}

定义注解的实现类

@Component
@Aspect
@Slf4j
public class TargetDataSourceAspect {
    @Before("@within(TargetDataSource) || @annotation(TargetDataSource)")
    public void beforeNoticeUpdateDataSource(JoinPoint joinPoint){
        TargetDataSource annotation = null;
        Class<? extends Object> clazz = joinPoint.getTarget().getClass();
        if(clazz.isAnnotationPresent(TargetDataSource.class)){
            //判断类上是否标注着注解
            annotation = clazz.getAnnotation(TargetDataSource.class);
            log.info("类上标注着注解");
        }else {
            Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
            if (method.isAnnotationPresent(TargetDataSource.class)){
                //判断方法上是否标注着注解,若类或方法上都没有则报错
                annotation = method.getAnnotation(TargetDataSource.class);
            }else {
                throw new RuntimeException("@TargetDataSource注解只能用于类或者方法上, 错误出现在:[" +
                        clazz.toString() +" " + method.toString() + "];");
            }
        }
        DynamicDataSource.flag.set(annotation.value().name());
    }

    @Around("@within(TargetDataSource) || @annotation(TargetDataSource)")
    public Object aroundNoticeUpdateDataSource(ProceedingJoinPoint proceed){
        // 省略逻辑代码
        Object result = null;
        try {
            result = proceed.proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        return result;
    }
}

在有的博客中也会使用@Around环绕通知的方式,但是环绕通知需要执行joinPoint.process()方法来调用目标对象的方法,最后返回执行的值,不然得不到所需要的数据。
我这里使用了@Before前置通知,效果是一样的,因为@Around就会包含@Before。
ProceedingJoinPoint 对象只能在@Around环绕通知中使用,在其他通知中使用就会报错。

测试

@RestController
@TargetDataSource(DataSourceType.DB1) // 将注解标注在类上,表示本类中所有的方法都是使用数据源1
public class DeptController {
    @Autowired
    private DeptService deptService;

    @GetMapping(value = "/dept_list1")
    public List<Dept> dept1(){
        List<Dept> depts = deptService.list();
       return depts;
    }

    @GetMapping(value = "/dept_list2")
    public List<Dept> dept2(){
        List<Dept> depts = deptService.list();
        return depts;
    }
}
@RestController
public class Dept1Controller {
    @Autowired
    private DeptService deptService;

    @GetMapping(value = "/dept_list3")
    @TargetDataSource(DataSourceType.DB2) // 将注解标注在类上,表示本类中所有的方法都是使用数据源2
    public List<Dept> dept1(){
        List<Dept> depts = deptService.list();
        return depts;
    }

    @GetMapping(value = "/dept_list4")
    public List<Dept> dept2(){
        List<Dept> depts = deptService.list();
        return depts;
    }
}

方式四:通过SqlSessionFactory指定的数据源来操作指定目录的XML文件(分包方式整合)

**使用此方法则不会与上面所述的类有任何关系,本方法会重新定义类。**本方法也是一种推荐的方法,适用于对指定数据库的操作,也就是适合读写分离。不会存在代码冗余和存在硬编码。
使用此种方法不会存在任何代码的冗余以及硬编码的存在,但是需要分层明确。
唯一的不足就是添加一个数据源就需要重新写一个类,而这个类中的代码大部分又是相同的。
注意事项

  • 在 service 层中根据不同的业务注入不同的 dao 层
  • 如果是主从复制- -读写分离:比如 db1 中负责增删改,db2 中负责查询。但是需要注意的是负责增删改的数据库必须是主库(master)

所需资源(同方式一)

SpringBoot配置多数据源(同方式一)

在pom文件中引入依赖

同方式一

在properties文件中定义数据源所需的数据

同方式一

定义多个数据源

@Configuration
@MapperScan(basePackages = "com.study.multipleddatasource.mapper.db1", sqlSessionFactoryRef = "db1SqlSessionFactory")
public class DataSourceConfig1 {
    @Primary // 表示这个数据源是默认数据源, 这个注解必须要加,因为不加的话spring将分不清楚那个为主数据源(默认数据源)
    @Bean(name = "db1")
    @ConfigurationProperties(prefix = "spring.datasource.db1") //读取application.properties中的配置参数映射成为一个对象
    public DataSource dataSource1(){
        HikariDataSource hikariDataSource = DataSourceBuilder.create().type(HikariDataSource.class).build();
        return hikariDataSource;
    }

    @Primary
    @Bean("db1SqlSessionFactory")
    public SqlSessionFactory db1SqlSessionFactory(@Qualifier("db1") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        // mapper的xml形式文件位置必须要配置,不然将报错:no statement (这种错误也可能是mapper的xml中,namespace与项目的路径不一致导致)
        bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:mapping/db1/*.xml"));
        return bean.getObject();
    }

    @Primary
    @Bean("db1SqlSessionTemplate")
    public SqlSessionTemplate db1SqlSessionTemplate(@Qualifier("db1SqlSessionFactory") SqlSessionFactory sqlSessionFactory){
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}
@Configuration
@MapperScan(basePackages = "com.study.multipleddatasource.mapper.db2", sqlSessionFactoryRef = "db2SqlSessionFactory")
public class DataSourceConfig2 {
    @Primary // 表示这个数据源是默认数据源, 这个注解必须要加,因为不加的话spring将分不清楚那个为主数据源(默认数据源)
    @Bean(name = "db2")
    @ConfigurationProperties(prefix = "spring.datasource.db2") //读取application.properties中的配置参数映射成为一个对象
    public DataSource dataSource1(){
        HikariDataSource hikariDataSource = DataSourceBuilder.create().type(HikariDataSource.class).build();
        return hikariDataSource;
    }

    @Primary
    @Bean("db2SqlSessionFactory")
    public SqlSessionFactory db2SqlSessionFactory(@Qualifier("db2") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        // mapper的xml形式文件位置必须要配置,不然将报错:no statement (这种错误也可能是mapper的xml中,namespace与项目的路径不一致导致)
        bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:mapping/db2/*.xml"));
        return bean.getObject();
    }

    @Primary
    @Bean("db2SqlSessionTemplate")
    public SqlSessionTemplate db1SqlSessionTemplate(@Qualifier("db2SqlSessionFactory") SqlSessionFactory sqlSessionFactory){
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}
  1. @MapperScan注解中的basePackages指向的是指定的Dao层。
  2. @MapperScan注解中sqlSessionFactoryRef 用来指定使用某个SqlSessionFactory来操作数据源。
  3. bean.setMapperLocations(
    new PathMatchingResourcePatternResolver()
    .getResources(“classpath*:mapper/db1/*.xml”)); 指向的是操作执行数据库的Mapper层。
  4. 项目目录结构

image.png

测试

@SpringBootTest
class MultipledDataSourceApplicationTests {
    @Autowired
    private DeptMapper1 deptMapper1;

    @Autowired
    private DeptMapper2 deptMapper2;

    @Test
    void contextLoads() {
    }
    @Test
    public void test01(){
        List<Dept> depts1 = deptMapper1.list();
        System.out.println(depts1);
        List<Dept> depts2 = deptMapper2.list();
        System.out.println(depts2);
    }
}

方式五:使用第三方插件+注解形式

所需资源

  • spring-boot-starter-web
  • mybatis-plus-boot-starter
  • dynamic-datasource-spring-boot-starter # 配置动态数据源
  • mysql-connector-java
  • lombok

SpringBoot配置多数据源(同方式一)

在pom文件中引入依赖

方式一基础添加

<dependency>
  <groupId>com.baomidou</groupId>
  <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
  <version>3.5.0</version>
</dependency>

在properties文件中定义数据源所需的数据

spring.datasource.type=com.zaxxer.hikari.HikariDataSource

# 配置默认数据库
spring.datasource.dynamic.primary=db1
# 配置数据源1
spring.datasource.dynamic.datasource.db1.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.dynamic.datasource.db1.url=jdbc:mysql://localhost:3306/mbatis?useSSL=true&serverTimezone=Asia/Shanghai
spring.datasource.dynamic.datasource.db1.username=root
spring.datasource.dynamic.datasource.db1.password=root
# 配置数据源2
spring.datasource.dynamic.datasource.db2.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.dynamic.datasource.db2.url=jdbc:mysql://localhost:3306/test?useSSL=true&serverTimezone=Asia/Shanghai
spring.datasource.dynamic.datasource.db2.username=root
spring.datasource.dynamic.datasource.db2.password=root

mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
mybatis-plus.global-config.db-config.table-prefix=t_
mybatis-plus.global-config.db-config.id-type=auto

禁用掉Spring Boot的数据源自动配置类

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class ThirdPluginDataSourceApplication {

    public static void main(String[] args) {
        SpringApplication.run(ThirdPluginDataSourceApplication.class, args);
    }

}

测试(给使用非默认数据源添加注解@DS)

@DS 可以注解在方法上和类上,同时存在方法注解优先于类上注解。
注解在 service 实现或 mapper 接口方法上,不要同时在 service 和 mapper 注解。

@SpringBootTest
class ThirdPluginDataSourceApplicationTests {
    @Autowired
    private DeptMapper deptMapper;

    @Test
    void contextLoads() {
    }

    @DS("db1")
    @Test
    public void test01(){
        List<Dept> depts1 = deptMapper.selectList(null);
        System.out.println(depts1);
    }
}

总结

  • 实现DataSource接口这种写法是不推荐的。
  • 推荐使用Spring Boot + 自定义注解的方式与SqlSessionFactory方式。

另外,Spring AOP中各种通知的执行顺序如下图所示:

事务配置

开启事务管理功能

在项目入口类,添加以下注解开启事务管理功能。@EnableTransactionManagement

@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
@EnableTransactionManagement
public class DataSourceDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DataSourceDemoApplication.class, args);
    }

}

配置事务管理器

@Configuration
public class DataSourceConfig {

    @Bean(name = "db1")
    @ConfigurationProperties(prefix = "spring.datasource.db1")
    public DataSource dataSource1(){
        HikariDataSource hikariDataSource = DataSourceBuilder.create().type(HikariDataSource.class).build();
        return hikariDataSource;
    }

    @Bean(name = "db2")
    @ConfigurationProperties(prefix = "spring.datasource.db2")
    public DataSource dataSource2(){
        HikariDataSource hikariDataSource = DataSourceBuilder.create().type(HikariDataSource.class).build();
        return hikariDataSource;
    }

    @Bean("db1TransactionManager")
    public PlatformTransactionManager db1TransactionManager(@Qualifier("db1") DataSource dataSource){
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean("db2TransactionManager")
    public PlatformTransactionManager db2TransactionManager(@Qualifier("db2") DataSource dataSource){
        return new DataSourceTransactionManager(dataSource);
    }
}

使用

使用时只需在需要事务的方法添加注解@Transactional,并指定其value值即可。同样的,value值与相应的方法名相匹配即可。

@SpringBootTest
class DataSourceDemoApplicationTests {
    @Autowired
    private DeptService deptService;

    @Test
    void contextLoads() {
    }
    @Test
    public void test(){
        DynamicDataSource.flag.set("r");
        List<Dept> depts1 = deptService.list();
        System.out.println(depts1);
        DynamicDataSource.flag.set("w");
        List<Dept> depts2 = deptService.list();
        System.out.println(depts2);
    }
    @Transactional("db1TransactionManager")
    @Test
    public void test01(){
        DynamicDataSource.flag.set("r");
        List<Dept> depts1 = deptService.list();
        System.out.println(depts1);
    }
    @Transactional("db2TransactionManager")
    @Test
    public void test02(){
        DynamicDataSource.flag.set("w");
        List<Dept> depts2 = deptService.list();
        System.out.println(depts2);
    }
}

注意,@Transactional配置事务有很多限制,如方法必须为public,同一个类中无该注解的方法调用有注解的方法事务不生效等。该注解还可以配置在接口类等地方,具体用法请参考Spring官方文档相应章节http://docs.spring.io/spring-framework/docs/4.2.x/spring-framework-reference/html/transaction.html

Gitee代码链接:
https://gitee.com/zhangcijuan/DynamicDataSource

参考链接:

https://m.jb51.net/program/29100498g.htm

https://m.jb51.net/article/110734.htm

  • 20
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于Spring Boot分库分表的项目实战,你可以按照以下步骤进行: 1. 配置数据源:在Spring Boot项目的配置文件中,添加多个数据源配置,用于连接不同的数据库。可以使用Spring Boot提供的多数据源配置,或者自己实现多数据源的Bean。 2. 配置分库分表策略:选择合适的分库分表策略,常见的有垂直分库、水平分库、垂直分表、水平分表等。根据具体业务需求,配置相应的分库分表规则。 3. 使用分库分表中间件:引入适合的分库分表中间件,如ShardingSphere、MyCAT等。根据中间件的文档和配置方式,进行相应的配置,使得中间件能够根据配置的规则将数据进行分库分表。 4. 数据访问层设计:在数据访问层(DAO)中,需要根据具体的业务需求,按照分库分表规则进行查询和操作。可以使用中间件提供的API或者自行编写相关代码。 5. 单元测试和压力测试:在开发过程中,务必编写相应的单元测试用例,验证分库分表的功能是否正常。同时,进行压力测试,模拟多种并发情况下的数据库访问,查看系统的性能是否满足需求。 6. 监控和调优:在项目上线后,需要进行系统的监控和性能调优。监控数据库的负载情况,根据实际情况进行调整分库分表的配置和规则,以保证系统的稳定性和性能。 以上是Spring Boot分库分表的一个简单实战流程,具体的实现方式会根据业务需求和技术栈的不同而有所差异。希望对你有所帮助!如果有其他问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值