Springboot integrates JPA multiple data sources (Oracle+Mysql)

1. Maven

<dependency>
   <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- 数据库连接池 -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.2.9</version>
</dependency>
<dependency>
    <groupId>com.oracle.database.jdbc</groupId>
    <artifactId>ojdbc8</artifactId>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.16</version>
</dependency>

2. Basic configuration

2.1 DataSource

In the basic configuration, we first configure the basic information of multiple data sources and DataSource, first add the following configuration information in application.yml:

spring:
  datasource:
    # oracle数据库配置
    oracle:
      driver-class-name: oracle.jdbc.driver.OracleDriver
      url: jdbc:oracle:thin:@localhost:1521:orcl
      username: test
      password: test
    # mysql数据库配置
    mysql:
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://localhost:3306/swap_business_db?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai
      username: root
      password: root
    type: com.alibaba.druid.pool.DruidDataSource
    # druid数据库连接池
    druid:
      filters: stat
      initialSize: 5
      maxActive: 20
      maxPoolPreparedStatementPerConnectionSize: 20
      maxWait: 60000
      minEvictableIdleTimeMillis: 30000
      minIdle: 5
      poolPreparedStatements: false
      testOnBorrow: false
      testOnReturn: false
      testWhileIdle: true
      timeBetweenEvictionRunsMillis: 60000
      #Oracle模式
      validation-query: SELECT 1 FROM DUAL #用来检测连接是否有效的sql
      #MySQL模式
      validation-queryM: SELECT 1 #用来检测连接是否有效的sql
  jpa:
    hibernate:
      ddl-auto: none
      oracle-dialect: org.hibernate.dialect.Oracle10gDialect
      mysql-dialect: org.hibernate.dialect.MySQL8Dialect
    show-sql: false

Next, configure two DataSources, as follows:

@Configuration
public class DataSourceConfig {
    
    

    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.oracle")
    @Primary
    DataSource dsOracle() {
    
    
        return DruidDataSourceBuilder.create().build();
    }

    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.mysql")
    DataSource dsMysql() {
    
    
        return DruidDataSourceBuilder.create().build();
    }
}

Note:@Primary , this annotation must not be missing, otherwise an error will occur when the project starts. @Primary indicates which instance is used first when there are multiple instances of a certain class.

3. Multiple data source configuration

Next, configure the basic information of Jpa. Here, the two data sources are configured in two classes respectively. The oracle and mysql configurations are as follows:

3.1 JpaConfigOracle

@Configuration
@EnableJpaRepositories(basePackages = "cn.piesat.dao.oracle",
        entityManagerFactoryRef = "localContainerEntityManagerFactoryBeanOracle",
        transactionManagerRef = "platformTransactionManagerOracle")
public class JpaConfigOracle {
    
    
    @Autowired
    @Qualifier(value = "dsOracle")
    DataSource dsOracle;

    @Autowired
    JpaProperties jpaProperties;
    @Autowired
    private HibernateProperties hibernateProperties;

    @Value("${spring.jpa.hibernate.oracle-dialect}")
    private String oracleDialect;
    @Value("${spring.jpa.show-sql}")
    private String showSql;


    @Bean
    @Primary
    LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBeanOracle(EntityManagerFactoryBuilder builder) {
    
    
        return builder.dataSource(dsOracle)
                .packages("cn.piesat.model")
                .properties(getVendorProperties())
                .persistenceUnit("pu1")
                .build();
    }

    /**
     * 设置数据源属性
     *
     * @return
     */
    private Map<String, Object> getVendorProperties() {
    
    
        Map<String, String> map = new HashMap<>();
        // 设置oracle数据库方言
        map.put("hibernate.dialect", oracleDialect);
        map.put("show-sql", showSql);
        jpaProperties.setProperties(map);
        return hibernateProperties.determineHibernateProperties(
                jpaProperties.getProperties(), new HibernateSettings());
    }

    /**
     * 配置事务管理器
     *
     * @param builder
     * @return
     */
    @Bean
    PlatformTransactionManager platformTransactionManagerOracle(EntityManagerFactoryBuilder builder) {
    
    
        LocalContainerEntityManagerFactoryBean factoryBeanOracle = localContainerEntityManagerFactoryBeanOracle(builder);
        return new JpaTransactionManager(factoryBeanOracle.getObject());
    }
}

Configuration description: JpaPropertiesIt is an example provided by the system, and the data inside is the jpa-related configuration we configured in application.yml. HibernatePropertiesUsed to manually set data source properties, such as defining different database dialects. Then we provide two beans, namely LocalContainerEntityManagerFactoryBeanand PlatformTransactionManagertransaction manager, which are different from MyBatis and JdbcTemplate. In Jpa, transactions must be configured . When providing LocalContainerEntityManagerFactoryBean, you need to specify packages. The package specified here is the location of the entity class corresponding to this data source. In addition, the location of dao is specified by annotation on the configuration class here, and the corresponding references of LocalContainerEntityManagerFactoryBean and PlatformTransactionManager @EnableJpaRepositoriesrespectively name.

In this way, the first one is configured, and the second one is basically similar to this, with several main differences:

  • The location of the dao is different
  • persistenceUnit is different
  • The name of the related bean is different

3.2 JpaConfigMysql

@Configuration
@EnableJpaRepositories(basePackages = "cn.piesat.dao.mysql",
        entityManagerFactoryRef = "localContainerEntityManagerFactoryBeanMysql",
        transactionManagerRef = "platformTransactionManagerMysql")
public class JpaConfigMysql {
    
    
    @Autowired
    @Qualifier(value = "dsMysql")
    DataSource dsMysql;

    @Autowired
    JpaProperties jpaProperties;

    @Autowired
    private HibernateProperties hibernateProperties;

    @Value("${spring.jpa.hibernate.mysql-dialect}")
    private String mysqlDialect;
    @Value("${spring.jpa.show-sql}")
    private String showSql;


    @Bean
    LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBeanMysql(EntityManagerFactoryBuilder builder) {
    
    
        return builder.dataSource(dsMysql)
                .packages("cn.piesat.model")
                .properties(getVendorProperties())
                .persistenceUnit("pu2")
                .build();
    }

    /**
     * 设置数据源属性
     *
     * @return
     */
    private Map<String, Object> getVendorProperties() {
    
    
        Map<String, String> map = new HashMap<>();
        // 设置mysql数据库方言
        map.put("hibernate.dialect", mysqlDialect);
        map.put("show-sql", showSql);
        jpaProperties.setProperties(map);
        return hibernateProperties.determineHibernateProperties(
                jpaProperties.getProperties(), new HibernateSettings());
    }

    /**
     * 配置事务管理器
     *
     * @param builder
     * @return
     */
    @Bean
    PlatformTransactionManager platformTransactionManagerMysql(EntityManagerFactoryBuilder builder) {
    
    
        LocalContainerEntityManagerFactoryBean factoryBeanMysql = localContainerEntityManagerFactoryBeanMysql(builder);
        return new JpaTransactionManager(factoryBeanMysql.getObject());
    }
}

4. Dao layer interface

Next, provide the relevant entity classes and dao in the corresponding positions. Note: the entity classes can be shared, and the positions of the dao are different.

oracle interface:

package cn.piesat.dao.oracle;

public interface TMasOrbitInfoDao extends JpaRepository<TMasOrbitInfo, String> {
    
    
    List<TMasOrbitInfo> findBySatelliteAndObservationDateBetween(String satellite, String start, String end);
}

mysql interface:

package cn.piesat.dao.mysql;

public interface SwapBusinessEfficiencyMainDao extends JpaRepository<SwapBusinessEfficiencyMain, String> {
    
    
    List<SwapBusinessEfficiencyMain> findByDataIdentifyAndDataTimeBetween(String identify, String start, String end);
}

At this point, all configurations are completed, and then different Daos can be injected into the Service, and different Daos operate different data sources.

Guess you like

Origin blog.csdn.net/weixin_45698637/article/details/127869598