1. 程式人生 > >Java後端愛上SpringBoot 第四節:SpringBoot多資料來源

Java後端愛上SpringBoot 第四節:SpringBoot多資料來源

Java後端愛上SpringBoot 第四節:SpringBoot多資料來源


PS:配置多資料來源這個事情是專案中用到的,之前也做過dome,但是做的時候又踩了幾個坑,因此要記錄一下。

配置一個Oracle資料庫

先貼一下pom.xml檔案:

<?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.1.1.RELEASE</version> <relativePath /> <!-- lookup parent from repository --> </parent> <groupId>com.summit</groupId> <artifactId>summit-tas</artifactId> <version>0.0.1-SNAPSHOT</version> <name>SmartTAS</
name
>
<description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>net.sourceforge.jtds</groupId> <artifactId>jtds</artifactId> <version>1.2.6</version> </dependency> <dependency> <groupId>com.microsoft.sqlserver</groupId> <artifactId>mssql-jdbc</artifactId> <version>6.1.0.jre8</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-jpa</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.11</version><!--$NO-MVN-MAN-VER$ --> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>

我們配置一個主資料來源:primary

application.yml配置如下:

spring:
  datasource: 
    primary:
###運維庫
      driver-class-name: oracle.jdbc.driver.OracleDriver 
      jdbc-url: jdbc:oracle:thin:@//127.0.0.1:1521/ORCL
      username: oracle
      password: oracle
###驗證連線有效性
      test-while-idle: true
###獲取連線時候驗證,會影響效能
      test-on-borrow: false
###在連線歸還到連線池時是否測試該連線
      test-on-return: false
###空閒連接回收的時間間隔
      time-between-eviction-runs-millis: 300000
###連線池空閒連線的有效時間 ,設定30分鐘
      min-evictable-idle-time-millis: 1800000
###連線池配置
      maximum-pool-size: 50
      minIdle: 50
      connection-timeout: 30000
      max-lifetime: 1800000

新增一個DataSourcesConfig 用來配置資料來源的Bean
坑點一:
SpringBoot1.*的時候是spring.datasource.jdbcUrl,2.0的時候變成了spring.datasource.jdbc-url


import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

/**
 * 多資料來源配置
 * 
 * @Title: DataSourcesConfig.java
 * @Package com.summit.tas.cfg.db
 * @Description: TODO
 * @author hyn  
 * @date 2018年12月27日 下午3:43:53
 * @version V1.0  
 */
@Configuration
public class DataSourcesConfig {
	@Bean(name = "primaryDataSource")
	@Qualifier("primaryDataSource")
	@Primary
	@ConfigurationProperties(prefix = "spring.datasource.primary")
	public DataSource primaryDataSource() {
		return DataSourceBuilder.create().build();
	}
}

使用@Qualifier 來區分資料來源。
新增一個PrimaryConfig類:

package com.summit.tas.cfg.db;

import java.util.Properties;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
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;


@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(entityManagerFactoryRef = "entityManagerFactoryPrimary", transactionManagerRef = "transactionManagerPrimary", basePackages = {
		"com.summit.tas.primary.repository" })
//basePackages 為dao包,會自動掃面配置下面的包
public class PrimaryConfig {
	@Autowired 
	@Qualifier("primaryDataSource")
    private DataSource primaryDataSource;

	/**
	 * 主庫jpa 例項管理器工廠配置
	 */
	@Primary
	@Bean(name = "entityManagerFactoryPrimary")
	public LocalContainerEntityManagerFactoryBean entityManagerFactoryPrimary(EntityManagerFactoryBuilder builder) {
	//實體類的配置路徑
		LocalContainerEntityManagerFactoryBean em = builder.dataSource(primaryDataSource).packages("com.summit.tas.primary.dto")
				.build();
		Properties properties = new Properties();
		properties.setProperty("hibernate.physical_naming_strategy",
				"org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy");
		em.setJpaProperties(properties);
		return em;
	}

	/**
	 * 主庫事務管理器配置
	 */
	@Primary
	@Bean(name = "transactionManagerPrimary")
	public PlatformTransactionManager transactionManagerPrimary(EntityManagerFactoryBuilder builder) {
		JpaTransactionManager txManager = new JpaTransactionManager();
		txManager.setEntityManagerFactory(entityManagerFactoryPrimary(builder).getObject());
		return txManager;
	}
}

下面就可以進行增刪改查了。

配置一個SQLServer資料庫

再配一個SQLServer資料來源:
給application.yml新增以下配置:

    sydn:
      driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
      jdbc-url: jdbc:sqlserver://127.0.0.1:1433;database=cqswssydn
      username: sa
      password: 123456
    ###驗證連線有效性
      test-while-idle: true
###獲取連線時候驗證,會影響效能
      test-on-borrow: false
###在連線歸還到連線池時是否測試該連線
      test-on-return: false
###空閒連接回收的時間間隔
      time-between-eviction-runs-millis: 300000
###連線池空閒連線的有效時間 ,設定30分鐘
      min-evictable-idle-time-millis: 1800000
###連線池配置
      maximum-pool-size: 20
      minIdle: 20
      connection-timeout: 30000
      max-lifetime: 1800000

在DataSourcesConfig新增以下:

	@Bean(name = "sydnDataSource")
	@Qualifier("sydnDataSource")
	@ConfigurationProperties(prefix = "spring.datasource.sydn")
	public DataSource sydnDataSource() {
		return DataSourceBuilder.create().build();
	}

新增一個SydnConfig:

package com.summit.tas.cfg.db;

import java.util.Properties;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
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;

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(entityManagerFactoryRef = "entityManagerFactorySydn", transactionManagerRef = "transactionManagerSydn", basePackages = {
		"com.summit.tas.sydn.repository" })
public class SydnConfig {

	@Autowired
	@Qualifier("sydnDataSource")
	private DataSource sydnDataSource;

	/**
	 * sydn jpa 例項管理器工廠配置
	 */
	@Bean(name = "entityManagerFactorySydn")
	public LocalContainerEntityManagerFactoryBean entityManagerFactorySecondary(EntityManagerFactoryBuilder builder) {
		LocalContainerEntityManagerFactoryBean em = builder.dataSource(sydnDataSource).packages("com.summit.tas.sydn.dto")
				.build();
		Properties properties = new Properties();
		properties.setProperty("hibernate.physical_naming_strategy",
				"org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy");
		em.setJpaProperties(properties);
		return em;
	}

	/**
	 * sydn 事務管理器配置
	 */
	@Bean(name = "transactionManagerSydn")
	public PlatformTransactionManager transactionManagerSecondary(EntityManagerFactoryBuilder builder) {
		JpaTransactionManager txManager = new JpaTransactionManager();
		txManager.setEntityManagerFactory(entityManagerFactorySecondary(builder).getObject());
		return txManager;
	}
}

坑點二:
用sqlserver的時候不要用

		<dependency>
			<groupId>net.sourceforge.jtds</groupId>
			<artifactId>jtds</artifactId>
			<version>1.2.6</version>
		</dependency>

要用:

		<dependency>
			<groupId>com.microsoft.sqlserver</groupId>
			<artifactId>mssql-jdbc</artifactId>
			<version>6.1.0.jre8</version>
		</dependency>

配置一個MySql資料庫

再配一個MySql資料來源:
給application.yml新增以下配置:

    mysql:
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://127.0.0.1:3306/spring?useUnicode=true&characterEncoding=UTF-8&useSSL=false&autoReconnect=true&allowPublicKeyRetrieval=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai
      username: hyn
      password: hyn1234
###驗證連線有效性
      test-while-idle: true
###獲取連線時候驗證,會影響效能
      test-on-borrow: false
###在連線歸還到連線池時是否測試該連線
      test-on-return: false
###空閒連接回收的時間間隔
      time-between-eviction-runs-millis: 300000
###連線池空閒連線的有效時間 ,設定30分鐘
      min-evictable-idle-time-millis: 1800000
###連線池配置
      maximum-pool-size: 20
      minIdle: 20
      connection-timeout: 30000
      max-lifetime: 1800000

在DataSourcesConfig新增以下:

	@Bean(name = "mysqlDataSource")
	@Qualifier("mysqlDataSource")
	@ConfigurationProperties(prefix = "spring.datasource.mysql")
	public DataSource mysqlDataSource() {
		return DataSourceBuilder.create().build();
	}

新增一個MysqlConfig:

package com.summit.tas.cfg.db;

import java.util.Properties;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
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;

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(entityManagerFactoryRef = "entityManagerFactoryMysql", transactionManagerRef = "transactionManagerMysql", basePackages = {
		"com.summit.tas.mysql.repository" })
public class MysqlConfig {

	@Autowired
	@Qualifier("mysqlDataSource")
	private DataSource wdsDataSource;

	/**
	 * mysql jpa 例項管理器工廠配置
	 */
	@Bean(name = "entityManagerFactoryWds")
	public LocalContainerEntityManagerFactoryBean entityManagerFactorySecondary(EntityManagerFactoryBuilder builder) {
		LocalContainerEntityManagerFactoryBean em = builder.dataSource(wdsDataSource).packages("com.summit.tas.mysql.dto")
				.build();
		Properties properties = new Properties();
		properties.setProperty("hibernate.physical_naming_strategy",
				"org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy");
		em.setJpaProperties(properties);
		return em;
	}

	/**
	 * mysql 事務管理器配置
	 */
	@Bean(name = "transactionManagerW