【Spring】如何在单个Boot应用中配置多数据库?

 

 

原创 BOOT

为什么需要多数据库?

默认情况下,Spring Boot使用的是单数据库配置(通过spring.datasource.*配置具体数据库连接信息)。
对于绝大多数Spring Boot应用,这是符合其使用场景的,因为Spring Boot提倡的是微服务理念,每个应用对应一个单独的业务领域。但在某些特殊情况下,一个应用对应多个数据库又是无法避免的,例如实施数据库分库后原本单个数据库变为多个数据库。本文就结合实际代码介绍如何在单个Boot应用中配置多数据库,以及与之相关的Druid,jOOQ,Flyway等数据服务框架的配置改造。

配置示例

  • DB1,DB2: 两个示例数据库
  • ServiceA, ServiceB: 分别使用DB1和DB2的服务类
连接池Druid

Druid是阿里巴巴开源的数据库连接池,提供了强大的监控支持,号称Java语言中最好的连接池。

创建两个配置类分别注册对应DB1和DB2的DataSource Bean和TransactionManager Bean。以DB1为例:

Tip: 可以把其中一个配置类中注册的DataSource Bean和DataSourceTransactionManager Bean加上@Primary注解,作为默认装配实例。

// DB1
@Configuration
public class Db1Config {

    @Bean(initMethod = "init", destroyMethod = "close")
    @ConfigurationProperties(prefix = "db.db1")
    public DataSource dataSource1() {
        return new DruidDataSource();
    }

    @Bean
    public DataSourceTransactionManager transactionManager1() {
        DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
        transactionManager.setDataSource(dataSource1());
        return transactionManager;
    }
}

application.conf中的配置:

# DB1
db.db1.url=jdbc:mysql://127.0.0.1:3306/db1?useUnicode=true&characterEncoding=UTF-8&rewriteBatchedStatements=true
db.db1.username=root
db.db1.password=
ORM框架jOOQ

jOOQ是一个开源ORM框架,最大特点是提供类型安全的流式API,支持代码生成。

参照Boot自带的JooqAutoConfiguration,不难写出如下配置类:

@Configuration
public class JooqConfig {

    // DB1
    @Bean
    public DataSourceConnectionProvider dataSourceConnectionProvider1(
            @Qualifier("dataSource1") DataSource dataSource1) {
        return new DataSourceConnectionProvider(
                new TransactionAwareDataSourceProxy(dataSource1));
    }

    @Bean
    public SpringTransactionProvider transactionProvider1(
            @Qualifier("transactionManager1") DataSourceTransactionManager txManager1) {
        return new SpringTransactionProvider(txManager1);
    }

    // DB2
    // ...

    @Configuration
    public static class DslContextConfig {

        @Autowired(required = false)
        private RecordMapperProvider recordMapperProvider;

        @Autowired(required = false)
        private Settings settings;

        @Autowired(required = false)
        private RecordListenerProvider[] recordListenerProviders;

        @Autowired
        private ExecuteListenerProvider[] executeListenerProviders;

        @Autowired(required = false)
        private VisitListenerProvider[] visitListenerProviders;

        // DSLContext for DB1
        @Bean
        public DefaultDSLContext dslContext1(@Qualifier("dataSourceConnectionProvider1") DataSourceConnectionProvider connectionProvider1,
                                            @Qualifier("transactionProvider1") SpringTransactionProvider transactionProvider1) {
            return new DefaultDSLContext(configuration(connectionProvider1, transactionProvider1));
        }

        // DSLContext for DB2
        // ...

        private DefaultConfiguration configuration(ConnectionProvider connectionProvider, TransactionProvider transactionProvider) {
            DefaultConfiguration configuration = new DefaultConfiguration();
            configuration.setSQLDialect(SQLDialect.MYSQL);
            configuration.set(connectionProvider);
            configuration.set(transactionProvider);
            if (this.recordMapperProvider != null) {
                configuration.set(this.recordMapperProvider);
            }
            if (this.settings != null) {
                configuration.set(this.settings);
            }
            configuration.set(this.recordListenerProviders);
            configuration.set(this.executeListenerProviders);
            configuration.set(this.visitListenerProviders);
            return configuration;
        }
    }
}
服务类

配置好DataSource,TransacationManager和DSLContext之后,服务类的配置就比较简单了,直接引用即可。注意由于存在多套Beans,需要通过@Qualifier注解指定装配实例。

@Transactional("TransactionManager1")//每个事务指定 tx
public class ServiceA {

    @Autowired
    @Qualifier("dslContext1")
    protected DSLContext dsl;
}
数据库迁移框架Flyway

Flyway是一个轻量级的开源数据库迁移框架,使用非常广泛。

参照Boot自带的FlywayAutoConfiguration,同样可以写出如下配置类:

@Configuration
public class FlywayConfig {

    @Bean(initMethod = "migrate")
    @ConfigurationProperties(prefix = "fw.db1")
    public Flyway flyway(@Qualifier("dataSource1") DataSource dataSource1) {
        Flyway clinic = new Flyway();
        clinic.setDataSource(dataSource1);
        return clinic;
    }

    // DB2
    // ...

    /**
     * @see FlywayAutoConfiguration
     */
    @Bean
    @ConfigurationPropertiesBinding
    public StringOrNumberToMigrationVersionConverter stringOrNumberMigrationVersionConverter() {
        return new StringOrNumberToMigrationVersionConverter();
    }

    /**
     * Convert a String or Number to a {@link MigrationVersion}.
     * @see FlywayAutoConfiguration
     */
    private static class StringOrNumberToMigrationVersionConverter
            implements GenericConverter {

        private static final Set<ConvertiblePair> CONVERTIBLE_TYPES;

        static {
            Set<ConvertiblePair> types = new HashSet<ConvertiblePair>(2);
            types.add(new ConvertiblePair(String.class, MigrationVersion.class));
            types.add(new ConvertiblePair(Number.class, MigrationVersion.class));
            CONVERTIBLE_TYPES = Collections.unmodifiableSet(types);
        }

        @Override
        public Set<ConvertiblePair> getConvertibleTypes() {
            return CONVERTIBLE_TYPES;
        }

        @Override
        public Object convert(Object source, TypeDescriptor sourceType,
                              TypeDescriptor targetType) {
            String value = ObjectUtils.nullSafeToString(source);
            return MigrationVersion.fromVersion(value);
        }

    }
}

application.conf中的配置:

# DB1
fw.db1.enabled=true

关于事务

有经验的同学马上会问,多数据库下事务会不会有问题?需要改造成分布式事务吗?
只要为每个数据库创建独立的TransactionManager,就不会有问题,Spring会自动处理好事务的提交和回滚,就像单数据库一样。

至于分布式事务,大可不必,因为虽然有多个数据库,但仍然属于Local Transaction范畴。以后有时间我会再写篇文章展开阐述一下。

总结

由上可见,无论是基础的DataSource和TransactionManager,还是Spring之外的第三方框架,在Boot中基本都可以找到相应的AutoConfiguration配置类。参照这些配置类,就不难根据实际需要写出自己的扩展版本。对于那些找不到AutoConfiguration配置类的,可结合框架的官方文档,使用@Configuration和@Bean注解自行进行配置。

http://emacoo.cn/blog/spring-boot-multi-db

 

时间: 2024-10-31 15:35:08

【Spring】如何在单个Boot应用中配置多数据库?的相关文章

spring,struts2整合时web.xml中配置过滤器后部署报错

问题描述 <?xml version="1.0" encoding="UTF-8"?><web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://java.s

webconfig中配置各种数据库的连接字符串(转)

一.在appSettings配置 <appSettings>   <!--SQL Server--> <!--<add key="SQLString" value="Database=MyData;Data Source=NICKYAN-PC;User Id=sa;Password=123123;"/> <add key="DataDAL" value="RedGlovePermissio

asp.net-vs2012配置文件中配置了一个连接数据库的连接字符串运行后就出现以下几个错误

问题描述 vs2012配置文件中配置了一个连接数据库的连接字符串运行后就出现以下几个错误 我在vs2012配置文件中配置一个数据库的连接字符串,运行后就出现这几个错误 1.未能找到特性"type"的架构信息. 2.未能找到特性"value"的架构信息. 3.未能找到元素"defaultConnectionFactory"的架构信息. 4.未能找到元素"entityFramework"的架构信息. 5.未能找到元素"p

Spring Cloud连载(3)Spring Boot简介与配置

本站小福利 点我获取阿里云优惠券 原文作者:杨大仙的程序空间 3 Spring Boot简介与配置   3.1 Spring Boot         Spring Cloud基于Spring Boot搭建,本小节将对Spring Boot作一个大致的讲解,读者知道Spring Boot作用即可. 3.1.1 Spring Boot简介         开发一个全新的项目,需要先进行开发环境的搭建,例如要确定技术框架以及版本,还要考虑各个框架之间的版本兼容问题,完成这些繁琐的工作后,还要对新项目

struts2改spring boot过程中一些问题及解决办法记录

1.引入依赖包的问题 一般情况下,常用的jar包在maven仓库都可以找到,并能知道如何在pom.xml文件中配置,但是有时候需要在一些项目中使用一些我们自己写的代码生成的jar包,要引入maven中就需要做一些必要的处理. 我们项目中就有这样的情况存在,以下是处理方式之一,就是用maven的命令生成maven方式的jar,然后加入到本地库中引用,打包命令如下: mvn install:install-file -Dfile=huateng-comm-1.0.0.jar -DgroupId=co

了解Spring Boot的自动配置

Spring Boot的自动配置给开发者带来了很大的便利,当开发人员在pom文件中添加starter依赖后,maven或者gradle会自动下载很多jar包到classpath中.当Spring Boot检测到特定类的存在,就会针对这个应用做一定的配置,自动创建和织入需要的spring bean到程序上下文中. 在之前的文章中,我们只是在pom文件中增加各种starter的依赖,例如:spring-boot-starter-data-jpa, spring-boot-starter-web, s

Spring Boot的自动配置、Command-line Runner

接下来关于SpringBoot的一系列文章和例子,都来自<Spring Boot Cookbook>这本书,本文的主要内容是start.spring.io的使用.Spring Boot的自动配置以及CommandRunner的角色和应用场景. 1. start.spring.io的使用 首先带你浏览http://start.spring.io/,在这个网址中有一些Spring Boot提供的组件,然后会给你展示如何让你的Spring工程变得"Bootiful",我称之为&q

【spring boot】12.spring boot对多种不同类型数据库,多数据源配置使用

2天时间,终于把spring boot下配置连接多种不同类型数据库,配置多数据源实现! ====================================================================================================== spring boot对多种不同类型数据库,多数据源配置使用 多数据源配置相关官方API:https://docs.spring.io/spring-boot/docs/current/api/ 环境如下:

解析Java中如何获取Spring中配置的bean

本篇文章是对在Java中如何获取Spring中配置的bean进行了详细的分析介绍,需要的朋友参考下   一.什么是Spring?Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架 二.如何在程序中获取Spring配置的bean呢?方法一:在初始化时保存ApplicationContext对象代码: 复制代码 代码如下: ApplicationContext ac = new FileSystemXmlApplicationContex("applicationContex