1. 程式人生 > >spring boot2.0連線多資料來源

spring boot2.0連線多資料來源

1、附專案目錄結構圖

專案目錄

2、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>

	<groupId>com.dwb</groupId>
	<artifactId>spring-boot-multi-datasource</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>spring-boot-multi-datasource</name>
	<description>Demo project for Spring Boot</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.2.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>

		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>


</project>

3、主資料庫配置,需要注意的是dao、entity和DataSource的選擇,詳細見下面程式碼後的註釋

package com.dwb.springbootmultidatasource.conf;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
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.dwb.springbootmultidatasource.dao.primary"})          //指定dao路徑,資料庫操作
public class PrimaryDBConf {

    /**
     * 構建主資料來源
     *
     * @return
     */
    @Bean
    @Primary
    @Qualifier("primaryDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.primary")             //選擇主資料來源
    public DataSourceProperties primaryDataSourceProperties() {
        return new DataSourceProperties();
    }

    @Bean
    @Primary
    @Qualifier("primaryDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.primary")            //選擇主資料來源
    public DataSource primaryDataSource() {
        return primaryDataSourceProperties().initializeDataSourceBuilder().build();
    }

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

    @Autowired
    private JpaProperties jpaProperties;

    /**
     * HibernateSettings為配置列名生成策略,在yml中已經配置
     * spring boot1.5.* 中此方法有區別。返回的是DataSource,詳見spring-boot-examples下的spring-boot-multi-datasource示例
     *
     * @return
     */
    public Map<String, Object> getVerdorProperties() {
        return jpaProperties.getHibernateProperties(new HibernateSettings());
    }

    /**
     * entity管理工廠,指定entity位置
     *
     * @param builder
     * @return
     */
    @Primary
    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryPrimary(EntityManagerFactoryBuilder builder) {
        return builder
                .dataSource(primaryDataSource)
                .packages("com.dwb.springbootmultidatasource.entity.primary")          //指定entity路徑,欄位對映
                .properties(getVerdorProperties())
                .persistenceUnit("primaryPersistenceUnit")
                .build();
    }

    @Bean
    @Primary
    public EntityManager entityManagerPrimary(EntityManagerFactoryBuilder builder) {
        return entityManagerFactoryPrimary(builder).getObject().createEntityManager();
    }

    @Primary
    @Bean
    public PlatformTransactionManager transactionManagerPrimary(EntityManagerFactoryBuilder builder) {
        return new JpaTransactionManager(entityManagerFactoryPrimary(builder).getObject());
    }
}

4、從資料庫配置,需要注意的是dao、entity和DataSource的選擇,詳細見下面程式碼後的註釋

package com.dwb.springbootmultidatasource.conf;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
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 dwb
 * @create 2018-05-24 10:11
 */
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef = "entityManagerFactorySecondary",
        transactionManagerRef = "transactionManagerSecondary",
        basePackages = {"com.dwb.springbootmultidatasource.dao.secondary"}        //指定dao位置,資料庫操作
)
public class SecondaryDBConf {
    /**
     * 構建第二個資料來源
     *
     * @return
     */
    @Bean
    @Qualifier("seondaryDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.second")                 //選擇第二個資料來源
    public DataSourceProperties secondaryDataSourceProperties() {
        return new DataSourceProperties();
    }

    @Bean
    @Qualifier("secondaryDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.second")                //選擇第二個資料來源
    public DataSource secondaryDataSource() {
        return secondaryDataSourceProperties().initializeDataSourceBuilder().build();
    }

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

    @Autowired
    private JpaProperties jpaProperties;

    /**
     * HibernateSettings為配置列名生成策略,在yml中已經配置
     * spring boot1.5.* 中此方法有區別。返回的是DataSource,詳見spring-boot-examples下的spring-boot-multi-datasource示例
     *
     * @return
     */
    public Map<String, Object> getVendorProperties() {
        return jpaProperties.getHibernateProperties(new HibernateSettings());
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactorySecondary(EntityManagerFactoryBuilder builder) {
        return builder
                .dataSource(secondaryDataSource)
                .packages("com.dwb.springbootmultidatasource.entity.secondary")      //指定entity路徑,欄位對映
                .properties(getVendorProperties())
                .persistenceUnit("secondaryPersistenceUnit")
                .build();
    }

    @Bean
    public EntityManager entityManagerSecondary(EntityManagerFactoryBuilder builder) {
        return entityManagerFactorySecondary(builder).getObject().createEntityManager();
    }

    @Bean
    public PlatformTransactionManager transactionManagerSecondary(EntityManagerFactoryBuilder builder) {
        return new JpaTransactionManager(entityManagerFactorySecondary(builder).getObject());
    }
}

5、主資料來源對應的entity

package com.dwb.springbootmultidatasource.entity.primary;

import javax.persistence.*;
import java.io.Serializable;

@Table(name = "test_info")
@Entity
public class PrimaryTest implements Serializable {
    @Id
    @GeneratedValue
    @Column(name = "id")
    private Integer id;

    @Column(name = "age", columnDefinition = "int COMMENT '年齡'")
    private Integer age;

    @Column(name = "name", columnDefinition = "varchar(32) default null COMMENT '姓名'")
    private String name;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "TestInfo{" +
                "id=" + id +
                ", age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}

6、從資料對應的entity

package com.dwb.springbootmultidatasource.entity.secondary;

import javax.persistence.*;
import java.io.Serializable;

/**
 * 描述:
 *
 * @author dwb
 * @create 2018-05-18 23:58
 */
@Table(name = "wechat_approval_flag")
@Entity
public class SecondTest implements Serializable {
    @Id
    @GeneratedValue
    @Column(name = "id")
    private Integer id;

    @Column(name = "date")
    private String date;

    @Column(name = "flag")
    private Boolean flag;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getDate() {
        return date;
    }

    public void setDate(String date) {
        this.date = date;
    }

    public Boolean getFlag() {
        return flag;
    }

    public void setFlag(Boolean flag) {
        this.flag = flag;
    }

    @Override
    public String toString() {
        return "SecondTest{" +
                "id=" + id +
                ", date=" + date +
                ", flag=" + flag +
                '}';
    }
}

7、主資料來源的dao程式碼

package com.dwb.springbootmultidatasource.dao.primary;

import com.dwb.springbootmultidatasource.entity.primary.PrimaryTest;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface PrimaryDao extends JpaRepository<PrimaryTest, Integer> {
}

8、從資料來源的dao程式碼

package com.dwb.springbootmultidatasource.dao.secondary;

import com.dwb.springbootmultidatasource.entity.secondary.SecondTest;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface SecondDao extends JpaRepository<SecondTest, Integer> {
}

9、service類

package com.dwb.springbootmultidatasource.service;

import com.dwb.springbootmultidatasource.dao.primary.PrimaryDao;
import com.dwb.springbootmultidatasource.dao.secondary.SecondDao;
import com.dwb.springbootmultidatasource.entity.primary.PrimaryTest;
import com.dwb.springbootmultidatasource.entity.secondary.SecondTest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class GetInfoService {
    private static final Logger logger = LoggerFactory.getLogger(GetInfoService.class);

    @Autowired
    private PrimaryDao primaryDao;

    @Autowired
    private SecondDao secondDao;

    public void getInfo() {
        logger.info("service 開始,primary 開始...");
        List<PrimaryTest> listPrimary = primaryDao.findAll();
        logger.info("primary資料庫資料:" + listPrimary.toString());
        logger.info("primary 結束\nsecond 開始...");
        List<SecondTest> listSecond = secondDao.findAll();
        logger.info("second資料庫資料:" + listSecond.toString());
        logger.info("service 結束!");
    }
}

10、application.yml檔案,這裡選擇測試環境 

spring:
  profiles:
    active: prod

11、application-dev.yml檔案,具體的引數含義可自行百度

spring:
  profiles: dev
  datasource:
    primary:
      driver-class-name: com.mysql.jdbc.Driver
      url: jdbc:mysql://119.23.25.193/test?useUnicode=true&characterEncoding=utf-8&useSSL=false&autoReconnect=true
      name: root
      password: 123456
      maxActive: 20
      initialSize: 1
      maxWait: 600000
      minidle: 1
      timeBetweenEvictionRunsMillis: 600000
      minEvictableidleTimeMillis: 300000
      validationQuery: select 1
      testWhileIdle: true
      testOnBorrow: false
      testOnReturn: false
      poolPreparedStatements: true
      maxOpenPreparedStatements: 20

    second:
      driver-class-name: com.mysql.jdbc.Driver
      url: jdbc:mysql://119.23.25.193/attendance?useUnicode=true&characterEncoding=utf-8&useSSL=false&autoReconnect=true
      name: root
      password: 123456
      maxActive: 20
      initialSize: 1
      maxWait: 600000
      minidle: 1
      timeBetweenEvictionRunsMillis: 600000
      minEvictableidleTimeMillis: 300000
      validationQuery: select 1
      testWhileIdle: true
      testOnBorrow: false
      testOnReturn: false
      poolPreparedStatements: true
      maxOpenPreparedStatements: 20

    dbcp2:
      initial-size: 5
      max-wait-millis: 600000
      test-on-borrow: true

  jpa:
    database-platform: org.hibernate.dialect.MySQL5Dialect
#    hibernate:
#      ddl-auto: update
    show-sql: true

12、test類

package com.dwb.springbootmultidatasource;

import com.dwb.springbootmultidatasource.service.GetInfoService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringBootMultiDatasourceApplicationTests {

    @Autowired
    private GetInfoService getInfoService;

    @Test
    public void getInfo() throws Exception {
        getInfoService.getInfo();
    }
}