Spring Boot项目——SpringBoot2+JPA+druid配置多数据源

开发环境

  • SpringBoot:2.2.1RELEASE
  • druid:1.1.20
  • JPA:2.2.1RELEASE
  • maven:3.5.0
  • java:1.8
  • MySQL:8.0.12

步骤

  • pom.xml配置如下(只列出和文章有关的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 http://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.2.1.RELEASE</version>
              <relativePath/> <!-- lookup parent from repository -->
          </parent>
          <groupId>superviserServer</groupId>
          <artifactId>com.test.superviser.server</artifactId>
          <version>1.0-SNAPSHOT</version>
      
          <name>superviserServer</name>
          <description>SuperviserServer Service of Test, Inc.</description>
          <properties>
              <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
              <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
              <java.version>1.8</java.version>
              <resource.delimiter>@</resource.delimiter>
              <spring-boot-starter.version>2.2.1.RELEASE</spring-boot-starter.version>
          </properties>
      <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>5.2.1.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>${spring-boot-starter.version}</version> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <version>${spring-boot-starter.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> <version>${spring-boot-starter.version}</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.1.20</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.12</version> <exclusions> <exclusion> <artifactId>protobuf-java</artifactId> <groupId>com.google.protobuf</groupId> </exclusion> </exclusions> </dependency> </dependencies> </project>
  • application.yml文件配置如下
    • spring:
        datasource:
          driverClassName: com.mysql.cj.jdbc.Driver
      
          # 使用 alibaba druid 连接池、监控
          type: com.alibaba.druid.pool.DruidDataSource
          druid:
            primary :
              url: jdbc:mysql://localhost:3306/XXXXX?useUnicode=true&CharSet=utf8mb4&characterEncoding=utf8&characterSetResults=utf8&autoReconnect=true&autoReconnectForPools=true&rewriteBatchedStatements=true&allowMultiQueries=true&useSSL=false&serverTimezone=Asia/Shanghai
              username: XXXX
              password: XXXX
            secondary :
              url: jdbc:mysql://localhost:3306/XXXXXXX?useUnicode=true&CharSet=utf8mb4&characterEncoding=utf8&characterSetResults=utf8&autoReconnect=true&autoReconnectForPools=true&rewriteBatchedStatements=true&allowMultiQueries=true&useSSL=false&serverTimezone=Asia/Shanghai
              username: XXXX
              password: XXXX
            initial-size: 2
            min-idle: 5
            max-active: 10
            max-wait: 5000
            validation-query: SELECT 1
            test-on-borrow: false
            test-while-idle: true
            time-between-eviction-runs-millis: 18800
            web-stat-filter:
              enabled: true
              exclusions: js,gif,jpg,png,css,ico,/druid/*
            stat-view-servlet:
              enabled: true
              login-username: root
              login-password: druid2019
        jpa:
          hibernate:
            ddlAuto: update
          databasePlatform: org.hibernate.dialect.MySQL5InnoDBDialect
          showSql: true
    • 注意
      • yml文件中之所以把driverClassName放到datasource下面,是因为这个datasource属性是两个数据源共有的信息,所以可以共享。完全可以把driverClassName单独配置到每个数据源当中,效果是一样的
  • 配置primary和secondary两个数据源
    • package ***************************;
      
      import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
      import org.slf4j.Logger;
      import org.springframework.boot.context.properties.ConfigurationProperties;
      import org.springframework.context.annotation.Bean;
      import org.springframework.context.annotation.Configuration;
      import org.springframework.context.annotation.Primary;
      
      import javax.sql.DataSource;
      
      /**
       * @author *******
       * @Description: 多数据源配置
       * @date 2020/4/22
       */
      @Configuration
      public class DataSourceConfig {
      
          private static final Logger log = org.slf4j.LoggerFactory.getLogger(DataSourceConfig.class);
      
          @Primary
          @Bean(value = "primaryDataSource",initMethod = "init")
          @ConfigurationProperties("spring.datasource.druid.primary") //标红为yml文件中数据源路径:primary
          public DataSource dataSourceOne(){
              log.info("Init DataSourceOne");
              return DruidDataSourceBuilder.create().build();
          }
      
          @Bean(value = "secondDataSource",initMethod = "init")
          @ConfigurationProperties("spring.datasource.druid.secondary")//标红为yml文件中数据源路径:secondary
          public DataSource dataSourceTwo(){
              log.info("Init DataSourceTwo");
              return DruidDataSourceBuilder.create().build();
          }
      }
    • 注意
      • 多数据源配置时,一定要区分主数据源和其他数据源。所以在主数据源初始化时一定要加上注解@Peimary,其余数据源初始化不可以使用这个注解,否则报错。
  • 对应不同的数据源,需要匹配不同的JPA
    • 主数据源primary JPA配置如下
      • package ***************************;
        
        /**
         * @author ******
         * @Description: 主数据源 配置
         * @date 2020/4/22
         */
        
        import org.springframework.beans.factory.annotation.Autowired;
        import org.springframework.beans.factory.annotation.Qualifier;
        import org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties;
        import org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings;
        import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
        import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
        import org.springframework.context.annotation.Bean;
        import org.springframework.context.annotation.Configuration;
        import org.springframework.context.annotation.Primary;
        import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
        import org.springframework.orm.jpa.JpaTransactionManager;
        import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
        import org.springframework.transaction.PlatformTransactionManager;
        import org.springframework.transaction.annotation.EnableTransactionManagement;
        
        import javax.persistence.EntityManager;
        import javax.sql.DataSource;
        import java.util.Map;
        
        @Configuration
        @EnableTransactionManagement
        @EnableJpaRepositories(
                entityManagerFactoryRef = "entityManagerFactoryPrimary",
                transactionManagerRef = "transactionManagerPrimary",
                basePackages = {"com.xxxx.xxxxx.xxxxx.xxxx.repositories.mysql.record"}) //设置Repository所在位置
        public class PrimaryJpaConfig {
            @Autowired
        //    @Qualifier("primaryJpaProperties")
            private JpaProperties jpaProperties;
            @Autowired
            private HibernateProperties hibernateProperties;
        
            @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(jpaProperties.getProperties())// 设置jpa配置
                        .properties(getVendorProperties())// 设置hibernate配置
                        .packages("com.xxxxx.xxxxx.xxxx.xxxxx.entities.superviser") //设置实体类所在位置
                        .persistenceUnit("primaryPersistenceUnit")// 设置持久化单元名,用于@PersistenceContext注解获取EntityManager时指定数据源
                        .build();
            }
        
            private Map getVendorProperties() {
                return hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(), new HibernateSettings());
        
        //        return jpaProperties.getHibernateProperties(new HibernateSettings());
            }
        
            @Primary
            @Bean(name = "transactionManagerPrimary")
            public PlatformTransactionManager transactionManagerPrimary(EntityManagerFactoryBuilder builder) {
                return new JpaTransactionManager(entityManagerFactoryPrimary(builder).getObject());
            }
        
        }
      • 注意
        • 主数据源JPA配置中,相对应的注入bean一定要加上注解@Primary,否则报错
    • 第二数据源JPA配置如下
      • package *********************;
        
        import org.springframework.beans.factory.annotation.Autowired;
        import org.springframework.beans.factory.annotation.Qualifier;
        import org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties;
        import org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings;
        import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
        import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
        import org.springframework.context.annotation.Bean;
        import org.springframework.context.annotation.Configuration;
        import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
        import org.springframework.orm.jpa.JpaTransactionManager;
        import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
        import org.springframework.transaction.PlatformTransactionManager;
        import org.springframework.transaction.annotation.EnableTransactionManagement;
        
        import javax.persistence.EntityManager;
        import javax.sql.DataSource;
        import java.util.Map;
        
        /**
         * @author ********
         * @Description: 第二数据源配置
         * @date 2020/4/22
         */
        @Configuration
        @EnableTransactionManagement
        @EnableJpaRepositories(
                entityManagerFactoryRef = "entityManagerFactorySecond",
                transactionManagerRef = "transactionManagerSecond",
                basePackages = {"com.xxxxx.xxxxx.xxxx.xxxxx.repositories.mysql.integration"}) //设置Repository所在位置
        public class SecondJpaConfig {
            @Autowired
        //    @Qualifier("secondJpaProperties")
            private JpaProperties jpaProperties;
            @Autowired
            private HibernateProperties hibernateProperties;
        
            @Autowired
            @Qualifier("secondDataSource")
            private DataSource secondDataSource;
        
            @Bean(name = "secondEntityManager")
            public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
                return entityManagerFactorySecond(builder).getObject().createEntityManager();
            }
        
            @Bean(name = "entityManagerFactorySecond")
            public LocalContainerEntityManagerFactoryBean entityManagerFactorySecond(EntityManagerFactoryBuilder builder) {
                return builder
                        .dataSource(secondDataSource)
                        .properties(jpaProperties.getProperties())// 设置jpa配置
                        .properties(getVendorProperties())
                        .packages("com.xxxxxx.xxxxxx.xxxxxx.xxxxx.entities.integration") //设置实体类所在位置
                        .persistenceUnit("secondPersistenceUnit")
                        .build();
            }
        
            private Map getVendorProperties() {
                return hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(), new HibernateSettings());
        
        //        return jpaProperties.getHibernateProperties(new HibernateSettings());
            }
        
            @Bean(name = "transactionManagerSecond")
            public PlatformTransactionManager transactionManagerSecond(EntityManagerFactoryBuilder builder) {
                return new JpaTransactionManager(entityManagerFactorySecond(builder).getObject());
            }
        }
      • 注意
        • 除了主数据源,其他数据源JPA配置中,bean的注入方法都不能使用注解@Primary,否则报错
  • 成功启动

注意点

  • @Primary注解的使用
  • 目录结构中,JPA目录和实体类目录建议根据多数据源的配置进行分层,因为在多数据源配置中存在相关配置

 

posted @ 2020-04-22 22:47  话·醉月  阅读(5952)  评论(3编辑  收藏  举报