zoukankan      html  css  js  c++  java
  • 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()方法中进行手动设置(此教程都已设置好了!)
    
  • 相关阅读:
    HYSBZ 1500 [NOI2005]维修数列 splay
    The 15th Zhejiang University Programming Contest
    工作小助手-v1.0正式上线,欢迎体验!!!
    登录窗体登录失败但是MainForm依然弹出无法结束的解决方法
    报错'cannot change visible in onshow or onhide'
    release模式发布软件的方法
    发布软件时因为窗体自动加载次序不对导致报错00000000
    修改类别 (类实现)两种方法
    从记事本导入记录
    快速粘贴
  • 原文地址:https://www.cnblogs.com/hzcya1995/p/13317313.html
Copyright © 2011-2022 走看看