SpringBoot配置雙數據源(一個項目同時連接操作兩台數據庫)


本文章使用的是持久化框架為JPA,所以數據源也是基於JPA。采用的是SpringBoot2 + SpringDataJPA + MySQL + 雙數據源!

一、雙數據源的適用場景:
1、主從庫分離(數據庫讀寫分離)

2、數據遷移

3、系統版本升級,數據庫升級到另外一款

二、application.yml中配置
spring:
  jpa:
    hibernate:
      ddl-auto: create
      naming:
        physical-strategy: org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy
        implicit-strategy: org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy
    open-in-view: true
    show-sql: true
    generate-ddl: true
 
 
  datasource: #database
    primary:  # 3.0 Datasource
      jdbc-url: jdbc:mysql://127.0.0.1:3306/gtu?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
      username: root
      password: 123456
 
    secondary:  # 2.0 Datasource
      jdbc-url: jdbc:mysql://127.0.0.1:3306/gtu-not-completed?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
      username: root
      password: 123456
注:配置文件中需要指定兩個數據源,這里在配置的時候是沒有自動提示的,因為這是我們自定義的,需要在程序中動態讀取。

三、讀取application.yml配置的兩個數據源,並將其注入到Spring的IOC容器中
@Configuration
public class DataSourceConfig {
 
 
    @Bean(name = "primaryDataSource")
    @Qualifier("primaryDataSource")
    @Primary
    @ConfigurationProperties(prefix = "spring.datasource.primary")
    public DataSource primaryDataSource() {
        return DataSourceBuilder.create().build();
    }
 
    @Bean(name = "secondaryDataSource")
    @Qualifier("secondaryDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.secondary")
    public DataSource secondaryDataSource() {
        return DataSourceBuilder.create().build();
    }
 
}
注解解釋:

@Configuration:SpringBoot啟動將該類作為配置類,同配置文件一起加載

@Bean:將該實體注入到IOC容器中

@Qualifier:指定數據源名稱,與Bean中的name屬性原理相同,主要是為了確保注入成功

@Primary:指定主數據源

@ConfigurationProperties:將配置文件中的數據源讀取進到方法中,進行build

四、以類的方式配置兩個數據源
(1)主數據源(對應DataSourceConfig類中的primaryDataSource)

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef = "entityManagerFactoryPrimary",
        transactionManagerRef = "transactionManagerPrimary",
        basePackages = {"com.gtcloud.repository"})    // 指定該數據源操作的DAO接口包
public class PrimaryConfig {
 
    @Autowired
    @Qualifier("primaryDataSource")
    private DataSource primaryDataSource;
 
    @Primary
    @Bean(name = "entityManagerPrimary")
    public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
        return entityManagerFactoryPrimary(builder).getObject().createEntityManager();
    }
 
    @Primary
    @Bean(name = "entityManagerFactoryPrimary")
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryPrimary(EntityManagerFactoryBuilder builder) {
        return builder
                .dataSource(primaryDataSource)
                .properties(getVendorProperties())
                .packages("com.gtcloud.model")         //設置實體類所在位置
                .persistenceUnit("primaryPersistenceUnit")
                .build();
    }
 
    private Map getVendorProperties() {
        HashMap<String, Object> properties = new HashMap<>();
        properties.put("hibernate.dialect",
                env.getProperty("hibernate.dialect"));
        properties.put("hibernate.ddl-auto",
                "create");
        properties.put("hibernate.physical_naming_strategy",
                "org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy");
        properties.put("hibernate.implicit_naming_strategy",
                "org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy");
        return properties;
    }
 
    @Autowired
    private Environment env;
 
    @Primary
    @Bean(name = "transactionManagerPrimary")
    public PlatformTransactionManager transactionManagerPrimary(EntityManagerFactoryBuilder builder) {
        return new JpaTransactionManager(entityManagerFactoryPrimary(builder).getObject());
    }
 
}


(2)從(次)數據源

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef = "entityManagerFactorySecondary",
        transactionManagerRef = "transactionManagerSecondary",
        basePackages = {"com.gtmove.repository"}) //設置DAO接口層所在包位置
public class SecondaryConfig {
 
    @Autowired
    @Qualifier("secondaryDataSource")
    private DataSource secondaryDataSource;
 
    @Bean(name = "entityManagerSecondary")
    public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
        return entityManagerFactorySecondary(builder).getObject().createEntityManager();
    }
 
    @Bean(name = "entityManagerFactorySecondary")
    public LocalContainerEntityManagerFactoryBean entityManagerFactorySecondary(EntityManagerFactoryBuilder builder) {
        return builder
                .dataSource(secondaryDataSource)
                .properties(getVendorProperties())
                .packages("com.gtmove.model")        //設置實體類所在包的位置
                .persistenceUnit("primaryPersistenceUnit")
                .build();
    }
 
    private Map getVendorProperties() {
        HashMap<String, Object> properties = new HashMap<>();
        properties.put("hibernate.hbm2ddl.auto",
                env.getProperty("hibernate.hbm2ddl.auto"));
        properties.put("hibernate.ddl-auto",
                env.getProperty("update"));
        properties.put("hibernate.dialect",
                env.getProperty("hibernate.dialect"));
        properties.put("hibernate.physical_naming_strategy",
                "org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy");
        properties.put("hibernate.implicit_naming_strategy",
                "org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy");
        return properties;
    }
 
    @Autowired
    private Environment env;
 
    @Bean(name = "transactionManagerSecondary")
    PlatformTransactionManager transactionManagerSecondary(EntityManagerFactoryBuilder builder) {
        return new JpaTransactionManager(entityManagerFactorySecondary(builder).getObject());
    }
}
這兩個類主要配置每個數據源,包括事務管理器、以及實體管理器等配置。

注:必須要指定DAO接口所在的包以及實體類所在的包。每個數據源主要操作它指定的資源(DAO接口CURD、實體類)

五、注意點:
1、SpringBoot啟動類必須關閉 --程序啟動加載的倉庫(@EnableJpaRepositories),因為在數據源配置類中已經開啟了。如果沒有去掉,程序會跑不起來!

@SpringBootApplication(scanBasePackages = {""})  // 指定加載程序主包,存在默認值【可選】
//@EntityScan({""})
//@EnableJpaRepositories(basePackages = {""})
public class Gt3datamoverApplication {
 
    public static void main(String[] args) {
        SpringApplication.run(Gt3datamoverApplication.class, args);
    }
 
}
2、如果需要對數據源連接的表進行DDL(正向生成表、程序啟動動態更新表),需要在PrimaryConfig類中 / SecondaryConfig類中的getVendorProperties()方法中進行手動設置(此教程都已設置好了!)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM