1. 程式人生 > >歷史上最詳細的SpringBoot多資料來源配置及使用流程

歷史上最詳細的SpringBoot多資料來源配置及使用流程

關於標題—>只是想看看標題黨的效果如何

一、場景(簡化)

要實現一個使用者資料中心的系統架構,其中要用到兩個資料庫,一個database名為sso,主要存放使用者的資訊。另一個database名為configuration,存放一些配置資訊。當A系統通過介面過來請求使用者資訊時,需要在配置庫查詢A系統的許可權,然後將對應許可權的使用者資訊返回給A系統。所以就需要使用兩個不同的庫,要在同一個專案中配置兩套EntityManager(或者Hibernate的session)和事物管理。

連線池使用阿里巴巴的Druid,持久框架使用的Hibernate,需要引入spring-boot-starter-data-jpa

二、實體的包結構

  • com.kingboy.configuration.domain(配置中心的實體)
  • com.kingboy.ssoservice.domain(使用者資訊的實體)

三、配置檔案(application.properties)

分別編寫兩套資料來源的配置,我主要用不同的模組名稱來區分不同的資料來源。

  • spring.datasource.configuration.*
  • spring.datasource.sso.*
#-----------------------------------通用資料來源配置-----------------------------
spring.jpa.hibernate.ddl-auto=update spring.jpa.open-in-view=false spring.jpa.show-sql=true #--------------------------------------------------------- #configuration資料來源 spring.datasource.configuration.url=jdbc:mysql://localhost:3306/configration?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false spring.datasource
.configuration.username=root spring.datasource.configuration.password=123456 spring.datasource.configuration.driver-class-name=com.mysql.jdbc.Driver spring.datasource.configuration.maxActive=20 spring.datasource.configuration.initialSize=5 spring.datasource.configuration.minIdle=5 spring.datasource.configuration.maxWait=60000 spring.datasource.configuration.maxPoolPreparedStatementPerConnectionSize=20 spring.datasource.configuration.timeBetweenEvictionRunsMillis=60000 spring.datasource.configuration.minEvictableIdleTimeMillis=300000 spring.datasource.configuration.poolPreparedStatements=true #--------------------------------------------------------- #sso資料來源 spring.datasource.sso.url=jdbc:mysql://localhost:3306/sso?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false spring.datasource.sso.username=root spring.datasource.sso.password=123456 spring.datasource.sso.driver-class-name=com.mysql.jdbc.Driver spring.datasource.sso.maxActive=20 spring.datasource.sso.initialSize=5 spring.datasource.sso.minIdle=5 spring.datasource.sso.maxWait=60000 spring.datasource.sso.maxPoolPreparedStatementPerConnectionSize=20 spring.datasource.sso.timeBetweenEvictionRunsMillis=60000 spring.datasource.sso.minEvictableIdleTimeMillis=300000 spring.datasource.sso.poolPreparedStatements=true

這麼多屬性一看就很萌逼了,我們先把它載入到一個資訊載體類中,方便以後使用。

configuration資料來源的資訊載體類:

package com.kingboy.configuration.config;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

/**
 * @Author kingboy
 * @Date 2017/6/19 下午5:15
 * @Description ConfigurationProperties is used to configuration的資料池屬性
 */
@ConfigurationProperties(prefix = "spring.datasource.configuration")
@Component
public class ConfigurationDataSourceProperties {

    public String url;

    public String username;

    public String password;

    public String driverClassName;

    public Integer maxActive;

    public Integer initialSize;

    public Integer minIdle;

    public Integer maxWait;

    public Integer maxPoolPreparedStatementPerConnectionSize;

    public Integer timeBetweenEvictionRunsMillis;

    public Integer minEvictableIdleTimeMillis;

    public Boolean poolPreparedStatements;

}

sso資料來源的資訊載體類:

package com.kingboy.ssoservice.config;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

/**
 * @Author kingboy
 * @Date 2017/6/19 下午5:15
 * @Description ConfigurationProperties is used to configuration的資料池屬性
 */
@ConfigurationProperties(prefix = "spring.datasource.sso")
@Component
public class SSODataSourceProperties {

    public String url;

    public String username;

    public String password;

    public String driverClassName;

    public Integer maxActive;

    public Integer initialSize;

    public Integer minIdle;

    public Integer maxWait;

    public Integer maxPoolPreparedStatementPerConnectionSize;

    public Integer timeBetweenEvictionRunsMillis;

    public Integer minEvictableIdleTimeMillis;

    public Boolean poolPreparedStatements;

}

四、配置configuration和sso的實體管理Bean和事物管理Bean

具體的配置說明都寫在程式碼註釋裡面了。

configuration的配置

package com.kingboy.configuration.config;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import org.springframework.beans.factory.annotation.Autowired;
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.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
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.sql.DataSource;
import java.util.Map;

/**
 * @Author kingboy
 * @Date 2017/6/18 下午11:13
 * @Description ConfigurationDataSource is used to 資料來源配置
 */
@Configuration
@EnableTransactionManagement//開啟事物管理
@EnableJpaRepositories(//自定義資料管理的配置
        //指定EntityManager的建立工廠Bean
        entityManagerFactoryRef="configurationEntityManagerFactory",
        //指定事物管理的Bean
        transactionManagerRef="configurationTransactionManager",
        //指定管理的實體位置
        basePackages= {"com.kingboy.configuration.domain"}) 
public class ConfigurationJPAConfig {

    /*
     * 配置資料來源
     */
    @Bean
    public DataSource configurationDataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        //設定資料來源的屬性
        setDruidProperties(dataSource);
        return dataSource;
    }

    @Autowired
    ConfigurationDataSourceProperties config;//注入資料來源配置資訊

    //設定資料來源的屬性的方法
    private void setDruidProperties(DruidDataSource dataSource) {
        dataSource.setUrl(config.url);
        dataSource.setUsername(config.username);
        dataSource.setPassword(config.password);
        dataSource.setDriverClassName(config.driverClassName);
        dataSource.setMaxActive(config.maxActive);
        dataSource.setInitialSize(config.initialSize);
        dataSource.setMinIdle(config.minIdle);
        dataSource.setMaxWait(config.maxWait);
        dataSource.setMaxPoolPreparedStatementPerConnectionSize(config.maxPoolPreparedStatementPerConnectionSize);
        dataSource.setTimeBetweenEvictionRunsMillis(config.timeBetweenEvictionRunsMillis);
        dataSource.setMinEvictableIdleTimeMillis(config.minEvictableIdleTimeMillis);
        dataSource.setPoolPreparedStatements(config.poolPreparedStatements);
    }

    /*
     * 配置實體管理工廠Bean
     */
    @Bean
    public LocalContainerEntityManagerFactoryBean configurationEntityManagerFactory (EntityManagerFactoryBuilder builder) {
        return builder
                .dataSource(configurationDataSource())
                .packages("com.kingboy.configuration.domain")//設定實體類所在位置
                .persistenceUnit("configuration")
                .properties(getProperties(configurationDataSource()))//設定hibernate通用配置
                .build();
    }

    @Autowired
    private JpaProperties jpaProperties;//注入spring自帶的jpa屬性類

    /*
     *拿到hibernate的通用配置
     */
    private Map<String, String> getProperties(DataSource dataSource) {
        return jpaProperties.getHibernateProperties(dataSource);
    }

    /*
     *配置事物管理的Bean
     */
    @Bean
    public PlatformTransactionManager configurationTransactionManager(EntityManagerFactoryBuilder builder) {
        return new JpaTransactionManager(configurationEntityManagerFactory(builder).getObject());
    }


}

sso的配置

package com.kingboy.ssoservice.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Autowired;
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.sql.DataSource;
import java.util.Map;

/**
 * @Author kingboy
 * @Date 2017/6/18 下午11:13
 * @Description ConfigurationDataSource is used to 資料來源配置
 */
@Configuration
@EnableTransactionManagement//開啟事物管理
@EnableJpaRepositories(//自定義資料管理的配置
        //指定EntityManager的建立工廠Bean
        entityManagerFactoryRef="ssoEntityManagerFactory",
        //指定事物管理的Bean
        transactionManagerRef="ssoTransactionManager",
        //指定管理的實體位置
        basePackages= {"com.kingboy.ssoservice.domain"}) //設定Repository所在位置
public class SSOJPAConfig {

    /*
     * 配置資料來源
     */
    @Bean
    @Primary//主資料來源,或者叫預設資料來源,下面的@Primary同理
    public DataSource ssoDataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        setDruidProperties(dataSource);
        return dataSource;
    }

    //注入資料來源配置資訊
    @Autowired
    SSODataSourceProperties config;

    private void setDruidProperties(DruidDataSource dataSource) {
        dataSource.setUrl(config.url);
        dataSource.setUsername(config.username);
        dataSource.setPassword(config.password);
        dataSource.setDriverClassName(config.driverClassName);
        dataSource.setMaxActive(config.maxActive);
        dataSource.setInitialSize(config.initialSize);
        dataSource.setMinIdle(config.minIdle);
        dataSource.setMaxWait(config.maxWait);
        dataSource.setMaxPoolPreparedStatementPerConnectionSize(config.maxPoolPreparedStatementPerConnectionSize);
        dataSource.setTimeBetweenEvictionRunsMillis(config.timeBetweenEvictionRunsMillis);
        dataSource.setMinEvictableIdleTimeMillis(config.minEvictableIdleTimeMillis);
        dataSource.setPoolPreparedStatements(config.poolPreparedStatements);
    }

    /*
     * 配置實體管理工廠Bean
     */
    @Bean
    @Primary
    public LocalContainerEntityManagerFactoryBean ssoEntityManagerFactory (EntityManagerFactoryBuilder builder) {
        return builder
                .dataSource(ssoDataSource())
                .packages("com.kingboy.ssoservice.domain") //設定實體類所在位置
                .persistenceUnit("sso")
                .properties(getProperties(ssoDataSource()))//設定hibernate通用配置
                .build();
    }

    @Autowired
    private JpaProperties jpaProperties;//注入spring自帶的jpa屬性類

    /*
     *拿到hibernate的通用配置
     */
    private Map<String, String> getProperties(DataSource dataSource) {
        return jpaProperties.getHibernateProperties(dataSource);
    }

    /*
     *配置事物管理的Bean
     */
    @Bean
    public PlatformTransactionManager ssoTransactionManager(EntityManagerFactoryBuilder builder) {
        return new JpaTransactionManager(ssoEntityManagerFactory(builder).getObject());
    }


}

五、關於第四節的說明

  1. @Bean註解如果沒有指定bean的名字,那麼會以方法名作為bean的名字。所以就有了@EnableJpaRepositories註解中的entityManagerFactoryRef="ssoEntityManagerFactory"transactionManagerRef="ssoTransactionManager"

  2. private JpaProperties jpaProperties;是spring自動注入的,可以獲取到配置檔案中『通用資料來源配置』的資訊,如show-sql等屬性。

  3. 只所以將sso與configuration分開配置,一是為了整潔。二是為了模組解耦,如果是多模組專案,會很好拆分。

六、使用

為了方便閱讀,隨便寫個栗子,就從controller開始寫了。也不使用介面程式設計了,這樣看起來更順暢。

實體類(註解就不加了)

public class User {
    private Integer id;
    private String telephone;
    private String password;
    //setter getter
}

public class Configuration {
    private Integer id;
    private String formatId;
    private String secret;
    //setter getter
}

Controller

@RestController
@RequestMapping(produces = "application/json")
public class UserController {

    @Resource
    UserService userService;

    @Resource
    ConfigurationService configurationService;

    /**
     * 新增User
     * @return
     */
    //為了方便用了restfule的形式,正常要用post,https
    @GetMapping(value = "/AddUser/{telephone}/{password}")
    public ApiResult add(@PathVariable String telephone, @PathVariable String password) {
        userService.addUser(telephone, password);
        return ApiResult.success("add user success!");
    }

    /**
     * 新增配置
     * @return
     */
    //為了方便用了restfule的形式,正常要用post,https
    @GetMapping(value = "/AddConfig/{formatId}/{secret}")
    public ApiResult add(@PathVariable String formatId, @PathVariable String secret) {
        configurationService.addConfig(formatId, secret);
        return ApiResult.success("add config success!");
    }

}

Service

@Service
public class UserServiceImpl{

    @Resource
    UserRepository userRepository;

    @Override
    @Transactional(rollbackFor = Exception.class, value = "ssoTransactionManager")//對應的事物管理Bean的名字
    public void addUser(String telephone,String password) {
        userRepository.addUser(telephone, password);
    }

}

@Service
public class ConfigurationServiceImpl{

    @Resource
    ConfigurationRepository configurationRepository;

    @Override
    @Transactional(rollbackFor = Exception.class, value = "configurationTransactionManager")//對應的事物管理Bean的名字
    public void addConfig(String formatId,String secret) {
        configurationRepository.addConfig(formatId, secret);
    }

}

Repository

@Repository
public class UserRepositoryImpl {

    @Autowired
    @Qualifier("ssoEntityManagerFactory")//實體管理工廠Bean的名字
    EntityManager ssoEntityManager;

    @Override
    public void addUser(String telephone, String password) {
        User user = new User(null, telephone, password);
        ssoEntityManager.persist(user);
    }

}

@Repository
public class ConfigurationRepositoryImpl {

    @Autowired
    @Qualifier("configurationEntityManagerFactory")//實體管理工廠Bean的名字
    EntityManager configurationEntityManager;

    @Override
    public void addConfig(String formatId, String secret) {
        Configuration config = new Configuration(null, formatId, secret);
        configurationEntityManager.persist(config);
    }

}

上面程式碼手寫,可能個別地方會有個小紕漏。

至此,全部搞定……m……m……p

相關推薦

歷史詳細SpringBoot資料來源配置使用流程

關於標題—>只是想看看標題黨的效果如何 一、場景(簡化) 要實現一個使用者資料中心的系統架構,其中要用到兩個資料庫,一個database名為sso,主要存放使用者的資訊。另一個database名為configuration,存放一些配置資訊。當

SpringBoot 資料來源配置

SpringBoot 多資料來源配置,查詢了好多方法,只有這個最好用. SpringBoot 多資料來源配置 檔案結構: DateSourceMultiple DataSourceType.java 註解動態切換資料庫 DruidConfig.java 載入資料來源

springboot資料來源配置事務

Springboot單資料來源時,事務直接在方法或者類上面使用@Transactional註解即可 對於多資料來源,需要在@Transactional中制定資料來源的transctionManager @Override @Transactional(rollbackF

Springboot資料來源配置--資料來源動態切換

在上一篇我們介紹了多資料來源,但是我們會發現在實際中我們很少直接獲取資料來源物件進行操作,我們常用的是jdbcTemplate或者是jpa進行操作資料庫。那麼這一節我們將要介紹怎麼進行多資料來源動態切換。新增本文實現的程式碼之後,只需要配置要資料來源就可以直接通過註解使用,

springBoot資料來源配置以及事務控制

一:多資料來源配置 1、主資料來源配置檔案 package com.bert.datasource; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.S

springboot 資料來源配置與使用

多資料來源配置 application.properties 配置兩個資料庫 #資料庫配置# spring.datasource.primary.driverClassName = com.mysql.jdbc.Driver spring.datasourc

詳細React Native環境配置專案初始化(2018-10-14)

注意配環境一定要全程使用穩定VPN工具,否則會浪費大量時間!!!相信我 一.截止到專案初始化之前也就是執行這條命令之前都按官網的方法就可以 https://reactnative.cn/docs/getting-started.html react-native ini

詳細Windows版本搭建安裝React Native環境配置

gin windows系統 adl 搭建環境 tools 想要 變量 rep home 說在前面的話: 感謝同事金曉冰傾情奉獻本環境搭建教程 之前我們已經講解了React Native的OS X系統的環境搭建以及配置,鑒於各大群裏有很多人反應在Windows環境搭建出現各種

實現SpringBoot資料來源配置

【場景】 當業務資料量達到了一定程度,DBA 需要合理配置資料庫資源。即配置主庫的機器高配置,把核心高頻的資料放在主庫上;把次要的資料放在從庫,低配置。 –(引自 https://www.cnblogs.com/Alandre/p/6611813.html 泥瓦匠BYSocket

springboot+mybatis資料來源配置,AOP註解動態切換資料來源

轉載至:https://blog.csdn.net/xiaosheng_papa/article/details/80218006 親測有效。 注:有些系統中已經配置了單資料來源,現在要轉成多資料來源,可能需要額外的配置。拿我自己當前專案來說: 專案在啟動類中配置了單資料來源:

談一談Spring-Mybatis在資料來源配置的坑

蘇格團隊 作者:JayceKon 交流QQ群:855833773 歡迎加入我們的團隊,微信聯絡方式:foreverpx_cjl 概述 先聊一聊業務背景,隨著系統服務的不斷開發,我們的系統會充斥著各種個樣的業務.這種時候,我們應該要開始考慮一下如何將系統的粒度細化.

談一談 Spring-Mybatis 在資料來源配置的坑

團隊部落格: https://juejin.im/post/5bfb607f6fb9a04a08215920 概述 先聊一聊業務背景,隨著系統服務的不斷開發,我們的系統會充斥著各種個樣的業務.這種時候,我們應該要開始考慮一下如何將系統的粒度細化.舉個常見的例子: 電商系統可以拆分為 商品模組,訂單模組,地

基於SpirngBoot2.0+ 的 SpringBoot+Mybatis 資料來源配置

Github 地址:github.com/Snailclimb/…(SpringBoot和其他常用技術的整合,可能是你遇到的講解最詳細的學習案例,力爭新手也能看懂並且能夠在看完之後獨立實踐。基於最新的 SpringBoot2.0+,是你學習SpringBoot 的最佳指南。) ,歡迎各位 Star。

新手也能看懂,基於SpirngBoot2.0+ 的 SpringBoot+Mybatis 資料來源配置

Github 地址:https://github.com/Snailclimb/springboot-integration-examples(SpringBoot和其他常用技術的整合,可能是你遇到的講解最詳細的學習案例,力爭新手也能看懂並且能夠在看完之後獨立實踐。基於最新的 S

SpringBoot資料來源連線池超時配置(MySQL+SQLServer)

單資料來源超時配置 spring.datasource.url=jdbc:mysql://127.0.0.1:3306/dcmserver?characterEncoding=utf-8 spring.datasource.username=root spring.data

springboot+mybatis+druid實現資料來源配置,支援註解和xml兩種sql書寫方式

https://github.com/cheegoday/springboot-demo-djg 要點: 一、依次建立以下幾個Bean 資料來源:DataSource session工廠:SqlSessionFactory 執行緒安全session:Sql

SpringBoot(三):資料來源配置

簡介 說起多資料來源,一般都來解決那些問題呢,主從模式或者業務比較複雜需要連線不同的分庫來支援業務,配置多資料來源重點是配置檔案,所以資料庫,pox檔案,實體類我都不發出來了,自己建立兩個資料庫,配置實體類就行了 版權宣告:本文由 低調小熊貓 發表於 低調小熊貓的部落格 轉

springboot+mybatis資料來源配置實現

簡單實現了根據註解動態切換資料來源,支援同一個資料庫的宣告式事務,但不支援JTA事務。處理流程: 根據配置的資料來源資訊,建立動態資料來源bean 利用DataSourceAspect處理@DataSource註解,設定當前要使用的具體資料來源 pom.xm

SpringBoot資料來源配置

在專案中需要在不同的IP裡的資料庫獲取資料,所以要求要可以靈活的指定具體要操作的資料庫。 主要使用的框架是spring-boot+mybatis等。 一:先將maven專案配置好(略); 二:springboot的啟動類: import org.apache.log4j.Lo

springboot v2.0.3版本資料來源配置

本篇分享的是springboot多資料來源配置,在從springboot v1.5版本升級到v2.0.3時,發現之前寫的多資料來源的方式不可用了,捕獲錯誤資訊如: 異常:jdbcUrl is required with driverClassName. 先來說下之前的多資料來源配置如: 1