SpringBoot配置多数据源(结合Druid)

在单数据源的情况下,Spring Boot的配置非常简单,只需要在application.properties文件中配置连接参数即可。但是往往随着业务量发展,我们通常会进行数据库拆分或是引入其他数据库,从而我们需要配置多个数据源,下面介绍多数据源的配置方式。

主要目录结构:主要关注红色方框中与本节相关的类。
这里写图片描述

  1. 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>

    <groupId>com.easted</groupId>
    <artifactId>card</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>card</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.6.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>
        <spring-cloud.version>Dalston.SR3</spring-cloud.version>
    </properties>

    <dependencies>
    <dependency>  <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency> 

            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-mail</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
        </dependency>
        <!-- 阿里的druid依赖 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.0.19</version>
        </dependency>
        <!-- 格式化对象,方便输出日志 -->  
        <dependency>  
            <groupId>com.alibaba</groupId>  
            <artifactId>fastjson</artifactId>  
            <version>1.1.41</version>  
        </dependency>  
        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <scope>runtime</scope>
        </dependency>
         <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- lombok 在类上加@Data可以省略get、set方法 -->
        <!-- <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <scope>provided</scope>
        </dependency> -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-rest</artifactId>
        </dependency>
        <dependency>
            <groupId>org.eclipse.persistence</groupId>
            <artifactId>javax.persistence</artifactId>
            <version>2.0.0</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.scala-lang</groupId>
            <artifactId>scala-library</artifactId>
            <version>2.11.0</version>
        </dependency>

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

        <dependency>
            <groupId>com.sun.jna</groupId>
            <artifactId>jna</artifactId>
            <version>3.0.9</version>
        </dependency>
        <dependency>
            <groupId>org.codehaus.jackson</groupId>
            <artifactId>jackson-mapper-asl</artifactId>
            <version>1.9.8</version>
            <type>jar</type>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jta-atomikos</artifactId>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

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


</project>
  1. application.yml
# Server configuration
server:
  port: 8090
  contextPath:

# Spring configuration
spring:
  thymeleaf: 
    cache: false
  mvc: 
    favicon:
      enabled: false
  #Multi DataSource Config
  datasource: 
     primary:
        type: com.alibaba.druid.pool.DruidDataSource
        url: jdbc:postgresql://127.0.0.1/db_one
        username: wangh
        password: easted2013
        driverClassName: org.postgresql.Driver
        initialSize: 5
        minIdle: 5
        maxActive: 200
        maxWait: 60000
        timeBetweenEvictionRunsMillis: 60000
        minEvictableIdleTimeMillis: 300000
        validationQuery: SELECT 'x'
        testWhileIdle: true
        testOnBorrow: false
        testOnReturn: false
        poolPreparedStatements: true
        maxPoolPreparedStatementPerConnectionSize: 20
        filters: stat,wall,log4j
        connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
     slave:
        type: com.alibaba.druid.pool.DruidDataSource
        url: jdbc:postgresql://127.0.0.1/db_two
        username: wangh
        password: easted2013
        driverClassName: org.postgresql.Driver
        initialSize: 5
        minIdle: 5
        maxActive: 200
        maxWait: 60000
        timeBetweenEvictionRunsMillis: 60000
        minEvictableIdleTimeMillis: 300000
        validationQuery: SELECT 'x'
        testWhileIdle: true
        testOnBorrow: false
        testOnReturn: false
        poolPreparedStatements: true
        maxPoolPreparedStatementPerConnectionSize: 20
        filters: stat,wall,log4j
        connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
  jpa:
    show-sql: true 
    hibernate: 
      ddl-auto: update
    properties:
      hibernate: 
        dialect: org.hibernate.dialect.PostgreSQLDialect
  1. DataSourceConfig类
package com.easted.card.core.config;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Qualifier;
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 com.alibaba.druid.pool.DruidDataSource;

/**
 1. @ClassName:DataSourceConfig
 2. @author:wh
 3. @date: 2017年9月12日 上午10:33:39
 */
@Configuration
public class DataSourceConfig {

    @Bean(name = "primaryDataSource")
    @Qualifier("primaryDataSource")
    @Primary//配置该数据源为主数据源
    @ConfigurationProperties(prefix = "spring.datasource.primary")
    public DataSource primaryDataSource(){
//      return DataSourceBuilder.create().build();
        return new DruidDataSource();
    }

    @Bean(name = "slaveDataSource")
    @Qualifier("slaveDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.slave")
    public DataSource secondDataSource(){
//      return DataSourceBuilder.create().build();
        return new DruidDataSource();
    }
}
  1. PrimaryConfig类
    新增对第一数据源的JPA配置,注意两处注释的地方,用于指定数据源对应的Entity实体和Repository定义位置,用@Primary区分主数据源。
package com.easted.card.core.config;

import java.util.HashMap;
import java.util.Map;

import javax.persistence.EntityManager;
import javax.sql.DataSource;

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

/**
 1. @ClassName:PrimaryConfig
 2. @author:Wh
 3. @date: 2017年9月13日 上午10:11:40
 */
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef="entityManagerFactoryPrimary",
        transactionManagerRef="transactionManagerPrimary",
        basePackages= { "com.easted.card.core.repository.primary"}) //设置Repository所在位置
public class PrimaryConfig {

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


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

    @Bean(name = "entityManagerFactoryPrimary")
    @Primary
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryPrimary (EntityManagerFactoryBuilder builder) {
        return builder.dataSource(primaryDataSource)
                .packages("com.easted.card.core.entity.postgre1")
                .persistenceUnit("primary")
                .properties(buildProperties())
                .build();
    } 

    @Bean(name="transactionManagerPrimary")
    @Autowired
    public PlatformTransactionManager primaryTransactionManager(EntityManagerFactoryBuilder builder) {
        return new JpaTransactionManager(entityManagerFactoryPrimary(builder).getObject());
    }

 // 公共jpa设置
    @Value("${spring.jpa.hibernate.ddl-auto}")
    String dll;
    @Value("${spring.jpa.properties.hibernate.dialect}")
    String dialect;
    @Value("${spring.jpa.show-sql}")
    String showSql;

    private Map<String, Object> buildProperties() {
        Map<String, Object> properties = new HashMap<String, Object>();
        properties.put("hibernate.ejb.naming_strategy", ImprovedNamingStrategy.class.getName());
        properties.put("hibernate.hbm2ddl.auto", dll);
        properties.put("hibernate.dialect", dialect);
        properties.put("hibernate.show_sql", showSql);
        return properties;
    }
}
  1. SlaveConfig类
package com.easted.card.core.config;

import java.util.HashMap;
import java.util.Map;

import javax.persistence.EntityManager;
import javax.sql.DataSource;

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

/**
 * SlaveConfig
 * @author:Wh
 * @date: 2017年9月13日 上午10:11:40
 */
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef="entityManagerFactorySlave",
        transactionManagerRef="transactionManagerSlave",
        basePackages= { "com.easted.card.core.repository.slave"}) //设置Repository所在位置
public class SlaveConfig {

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


    @Bean(name = "entityManagerSlave")
    public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
        return entityManagerFactorySlave(builder).getObject().createEntityManager();
    }

    @Bean(name = "entityManagerFactorySlave")
    public LocalContainerEntityManagerFactoryBean entityManagerFactorySlave(EntityManagerFactoryBuilder builder) {
        return builder.dataSource(slaveDataSource)
                .packages("com.easted.card.core.entity.postgre2")
                .persistenceUnit("slave")
                .properties(buildProperties())
                .build();
    } 

    @Bean(name="transactionManagerSlave")
    @Autowired
    public PlatformTransactionManager slaveTransactionManager(EntityManagerFactoryBuilder builder) {
        return new JpaTransactionManager(entityManagerFactorySlave(builder).getObject());
    }

 // 公共jpa设置
    @Value("${spring.jpa.hibernate.ddl-auto}")
    String dll;
    @Value("${spring.jpa.properties.hibernate.dialect}")
    String dialect;
    @Value("${spring.jpa.show-sql}")
    String showSql;

    private Map<String, Object> buildProperties() {
        Map<String, Object> properties = new HashMap<String, Object>();
        properties.put("hibernate.ejb.naming_strategy", ImprovedNamingStrategy.class.getName());
        properties.put("hibernate.hbm2ddl.auto", dll);
        properties.put("hibernate.dialect", dialect);
        properties.put("hibernate.show_sql", showSql);
        return properties;
    }
}
  1. DruidConfig类
package com.easted.card.core.config;

import java.util.HashMap;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.transaction.annotation.EnableTransactionManagement;

import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;

/**
 1. 配置Druid监控
 2. @ClassName:DruidDBConfig
 3. @author:Wh
 4. @date: 2017年8月23日 下午3:21:51
 */
@Configuration
@EnableTransactionManagement
public class DruidConfig{
    private static final Logger log = LoggerFactory.getLogger(DruidConfig.class);

    @Bean 
    public ServletRegistrationBean druidServlet() { 
        log.info("开始Druid Servlet初始化配置..."); 
        ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(); 
        servletRegistrationBean.setServlet(new StatViewServlet());
        servletRegistrationBean.addUrlMappings("/druid/*"); 
        Map<String, String> initParameters = new HashMap<String, String>(); 
        //用户名 
        initParameters.put("loginUsername", "wangh");
        //密码
        initParameters.put("loginPassword", "easted"); 
        // 禁用HTML页面上的“Reset All”功能 
        initParameters.put("resetEnable", "false");
        // IP白名单 (没有配置或者为空,则允许所有访问) 
        initParameters.put("allow", "127.0.0.1"); 
        // IP黑名单 (存在共同时,deny优先于allow) 
        initParameters.put("deny", "");
        servletRegistrationBean.setInitParameters(initParameters); 
        return servletRegistrationBean; 
    } 

    @Bean 
    public FilterRegistrationBean filterRegistrationBean() { 
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(); 
        filterRegistrationBean.setFilter(new WebStatFilter()); 
        filterRegistrationBean.addUrlPatterns("/*"); 
        filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"); 
        return filterRegistrationBean; 
    } 

}
  1. 实体类

在postgre1和postgre2包下分别建实体类。

package com.easted.card.core.entity.postgre1;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;



@Entity
public class Book {
    @Id
    @GeneratedValue
    private Integer id;
    private String name;

    /**
     * @Title: getId <BR>
     * @return:Integer <BR>
     */
    public Integer getId() {
        return id;
    }
    /**
     * @param id the id to set
     */
    public void setId(Integer id) {
        this.id = id;
    }
    /**
     * @Title: getName <BR>
     * @return:String <BR>
     */
    public String getName() {
        return name;
    }
    /**
     * @param name the name to set
     */
    public void setName(String name) {
        this.name = name;
    }


}
  1. primary包下BookRepository接口
package com.easted.card.core.repository.primary;

import org.springframework.data.jpa.repository.JpaRepository;

import com.easted.card.core.entity.postgre1.Book;
public interface BookRepository extends JpaRepository<Book, Integer> {

}
  1. slave包下BookRepository接口
package com.easted.card.core.repository.slave;

import org.springframework.data.jpa.repository.JpaRepository;

import com.easted.card.core.entity.postgre2.Book;
public interface BookRepository extends JpaRepository<Book, Integer> {

}

然后启动springboot.就可以了。
浏览器输入http://localhost:8090/druid/login.html
这里写图片描述

输入druidconfig配置的用户名密码。
这里写图片描述

这里写图片描述

可以看到有两个数据源。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值