Springboot多数据源集成jpa+druid

在用springboot开发项目时,随着业务量的扩大,我们通常会进行数据库拆分或是引入其他数据库,从而我们需要配置多个数据源,下面基于Spring-data-jpa配置多数据源,希望对大家有所帮助。

项目目录结构:
在这里插入图片描述

1、先在application.yml 中配置多个数据库:
spring:
  datasource:
    username: root
    password: 123456
    #或者写成database1也可以,因为这两个库中都为表tbl_user,表结构啥的都一样
    url: jdbc:mysql://localhost:3306/database3?characterEncoding=UTF-8&useSSL=false
    driver-class-name: com.mysql.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
    filters: stat
    database1:
      url: jdbc:mysql://localhost:3306/database1?useUnicode=true&characterEncoding=utf8&useSSL=false
      username: root
      password: 123456
      driverClassName: com.mysql.jdbc.Driver
#    database2:
#      url: jdbc:sqlserver://localhost:1433;DatabaseName=lf_jybtjcpg
#      username: sa
#      password: 123456
#      driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver
    database2:
      url: jdbc:mysql://localhost:3306/database2?useUnicode=true&characterEncoding=utf8&useSSL=false
      username: root
      password: 123456
      driverClassName: com.mysql.jdbc.Driver
      type: com.alibaba.druid.pool.DruidDataSource
      filters: stat
  jpa:
    database: mysql
    show-sql: true
    hibernate:
      ddl-auto: update
      naming:
        physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
    database-platform: org.hibernate.dialect.MySQL5Dialect

这里配置了database1、database2、database3(database3为了对比学习用,不是很规范)三个数据库

2、配置数据库连接属性

在DataBase1Properties类中配置database1数据库连接的属性

package com.hui.demo.config.properties;

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

@ConfigurationProperties(prefix = "spring.datasource.database1")
@Component
@Data
public class DataBase1Properties {
    private String url;

    private String username;

    private String password;

    private String driverClassName;

    public String getUrl()	{
        return url;
    }
    public void setUrl(String n) {
        url=n;
    }

    public String getUsername()	{
        return username;
    }
    public void setUsername(String n) {
        username=n;
    }

    public String getPassword()	{
        return password;
    }
    public void setPassword(String n) {
        password=n;
    }

    public String getDriverClassName()	{
        return driverClassName;
    }
    public void setDriverClassName(String n) {
        driverClassName=n;
    }
}

在DataBase2Properties类中配置database2数据库连接的属性:

package com.hui.demo.config.properties;

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

@ConfigurationProperties(prefix = "spring.datasource.database2")
@Component
@Data
public class DataBase2Properties {
    private String url;

    private String username;

    private String password;

    private String driverClassName;

    public String getUrl()	{
        return url;
    }
    public void setUrl(String n) {
        url=n;
    }

    public String getUsername()	{
        return username;
    }
    public void setUsername(String n) {
        username=n;
    }

    public String getPassword()	{
        return password;
    }
    public void setPassword(String n) {
        password=n;
    }

    public String getDriverClassName()	{
        return driverClassName;
    }
    public void setDriverClassName(String n) {
        driverClassName=n;
    }
}

在DataBase3Properties类中配置database3数据库连接的属性:

package com.hui.demo.config.properties;

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

@ConfigurationProperties(prefix = "spring.datasource") //这行不能注释掉,否则druid的“数据源”界面只会展示两个数据源而不是三个
@Component
@Data
public class DataBase3Properties {
    private String url;

    private String username;

    private String password;

    private String driverClassName;

    public String getUrl()	{
        return url;
    }
    public void setUrl(String n) {
        url=n;
    }

    public String getUsername()	{
        return username;
    }
    public void setUsername(String n) {
        username=n;
    }

    public String getPassword()	{
        return password;
    }
    public void setPassword(String n) {
        password=n;
    }

    public String getDriverClassName()	{
        return driverClassName;
    }
    public void setDriverClassName(String n) {
        driverClassName=n;
    }
}
3、数据库字段设置

在DataSourceConfig类中设置两个数据库的连接数据,可以使用springboot2.0默认的Hikari连接,也可以使用alibaba的druid

package com.hui.demo.config;

import com.hui.demo.config.properties.DataBase1Properties;
import com.hui.demo.config.properties.DataBase2Properties;
import com.hui.demo.config.properties.DataBase3Properties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import com.zaxxer.hikari.HikariDataSource;

import javax.sql.DataSource;

@Configuration
@Slf4j
public class DataSourceConfig {

    @Autowired
    private DataBase1Properties dataBase1Properties;

    @Autowired
    private DataBase2Properties dataBase2Properties;

    @Autowired
    private DataBase3Properties dataBase3Properties;

    @Bean(name = "dataBase1DataSource")
    @Primary
    public DataSource dataBase1DataSource(){
        System.out.println("dataBase1DataSource初始化----111111");
        HikariDataSource dataSource = new HikariDataSource();
        dataSource.setJdbcUrl(dataBase1Properties.getUrl());
        dataSource.setUsername(dataBase1Properties.getUsername());
        dataSource.setPassword(dataBase1Properties.getPassword());
        dataSource.setDriverClassName(dataBase1Properties.getDriverClassName());
        return dataSource;
    }

    @Bean(name = "dataBase2DataSource")
    public DataSource dataBase2DataSource(){
        System.out.println("dataBase2DataSource初始化----222222");
        HikariDataSource dataSource = new HikariDataSource();
        dataSource.setJdbcUrl(dataBase2Properties.getUrl());
        dataSource.setUsername(dataBase2Properties.getUsername());
        dataSource.setPassword(dataBase2Properties.getPassword());
        dataSource.setDriverClassName(dataBase2Properties.getDriverClassName());
        return dataSource;
    }

    @Bean(name = "dataBase3DataSource")
    public DataSource dataBase3DataSource(){
        System.out.println("dataBase3DataSource初始化----333333");
        HikariDataSource dataSource = new HikariDataSource();
        dataSource.setJdbcUrl(dataBase3Properties.getUrl());
        dataSource.setUsername(dataBase3Properties.getUsername());
        dataSource.setPassword(dataBase3Properties.getPassword());
        dataSource.setDriverClassName(dataBase3Properties.getDriverClassName());
        return dataSource;
    }
}

或者(二选一,也可以混着来,但是使用HikariDataSource的数据库不会出现在durid的“数据源”界面)

package com.hui.demo.config;

import com.alibaba.druid.pool.DruidDataSource;
import com.hui.demo.config.properties.DataBase1Properties;
import com.hui.demo.config.properties.DataBase2Properties;
import com.hui.demo.config.properties.DataBase3Properties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

import javax.sql.DataSource;

@Configuration
@Slf4j
public class DataSourceDruidConfig {

    @Autowired
    private DataBase1Properties dataBase1Properties;

    @Autowired
    private DataBase2Properties dataBase2Properties;

    @Autowired
    private DataBase3Properties dataBase3Properties;

    @Bean(name = "dataBase1DataSource")
    @Primary  // 对应的controller中的/query中的select * FROM tbl_user
    public DataSource dataBase1DataSource(){
        System.out.println("dataBase1DataSource初始化----111111");
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUrl(dataBase1Properties.getUrl());
        dataSource.setUsername(dataBase1Properties.getUsername());
        dataSource.setPassword(dataBase1Properties.getPassword());
        dataSource.setDriverClassName(dataBase1Properties.getDriverClassName());
        return dataSource;
    }

    @Bean(name = "dataBase2DataSource")
    // 如果把dataBase1DataSource的@Primary放这里会报错,因为dataBase2中没有tbl_user表,导致select * FROM tbl_user报错
    public DataSource dataBase2DataSource(){
        System.out.println("dataBase2DataSource初始化----222222");
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUrl(dataBase2Properties.getUrl());
        dataSource.setUsername(dataBase2Properties.getUsername());
        dataSource.setPassword(dataBase2Properties.getPassword());
        dataSource.setDriverClassName(dataBase2Properties.getDriverClassName());
        return dataSource;
    }

    @Bean(name = "dataBase3DataSource")
    public DataSource dataBase3DataSource(){
        System.out.println("dataBase3DataSource初始化----333333");
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUrl(dataBase3Properties.getUrl());
        dataSource.setUsername(dataBase3Properties.getUsername());
        dataSource.setPassword(dataBase3Properties.getPassword());
        dataSource.setDriverClassName(dataBase3Properties.getDriverClassName());
        return dataSource;
    }
}
4、配置数据源、连接工厂、事物管理器、dao目录

在DataBaseConfig1类中:

package com.hui.demo.config;

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

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef = "entityManagerFactoryDataBase1", // 配置连接工厂
        transactionManagerRef = "transactionManagerDatabase1", // 配置事物管理器
        basePackages = {"com.hui.demo.dao.database1"} // 设置dao所在位置
)

public class DataBase1Config {

    // 配置数据源
    @Autowired
    private DataSource dataBase1DataSource;

    @Primary
    @Bean(name = "entityManagerFactoryDataBase1")
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryDataBase1(EntityManagerFactoryBuilder builder) {
        return builder
                // 设置数据源
                .dataSource(dataBase1DataSource)
                //设置实体类所在位置.扫描所有带有 @Entity 注解的类
                .packages("com.hui.demo.entity.database1")
                // Spring会将EntityManagerFactory注入到Repository之中.有了 EntityManagerFactory之后,
                // Repository就能用它来创建 EntityManager 了,然后 EntityManager 就可以针对数据库执行操作
                .persistenceUnit("database1PersistenceUnit")
                .build();
    }

    /**
     * 配置事物管理器
     *
     * @param builder
     * @return
     */
    @Bean(name = "transactionManagerDatabase1")
    PlatformTransactionManager transactionManagerDatabase1(EntityManagerFactoryBuilder builder) {
        return new JpaTransactionManager(entityManagerFactoryDataBase1(builder).getObject());
    }
}

在DataBaseConfig2类中:

package com.hui.demo.config;

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;
import javax.sql.DataSource;

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef = "entityManagerFactoryDataBase2", // 配置连接工厂
        transactionManagerRef = "transactionManagerDatabase2", // 配置事物管理器
        basePackages = {"com.hui.demo.dao.database2"} // 设置dao所在位置
)

public class DataBase2Config {

    // 配置数据源
    @Autowired
    @Qualifier("dataBase2DataSource")
    private DataSource dataBase2DataSource;

    @Bean(name = "entityManagerFactoryDataBase2")
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryDataBase2(EntityManagerFactoryBuilder builder) {
        return builder
                // 设置数据源
                .dataSource(dataBase2DataSource)
                //设置实体类所在位置.扫描所有带有 @Entity 注解的类
                .packages("com.hui.demo.entity.database2")
                // Spring会将EntityManagerFactory注入到Repository之中.有了 EntityManagerFactory之后,
                // Repository就能用它来创建 EntityManager 了,然后 EntityManager 就可以针对数据库执行操作
                .persistenceUnit("database2PersistenceUnit")
                .build();
    }

    /**
     * 配置事物管理器
     *
     * @param builder
     * @return
     */
    @Bean(name = "transactionManagerDatabase2")
    PlatformTransactionManager transactionManagerDatabase2(EntityManagerFactoryBuilder builder) {
        return new JpaTransactionManager(entityManagerFactoryDataBase2(builder).getObject());
    }
}

在DataBaseConfig3类中:

package com.hui.demo.config;

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;
import javax.sql.DataSource;

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef = "entityManagerFactoryDataBase3", // 配置连接工厂
        transactionManagerRef = "transactionManagerDatabase3", // 配置事物管理器
        basePackages = {"com.hui.demo.dao.database3"} // 设置dao所在位置
)
public class DataBase3Config {

    // 配置数据源
    @Autowired
    @Qualifier("dataBase3DataSource")
    private DataSource dataBase3DataSource;

    @Bean(name = "entityManagerFactoryDataBase3")
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryDataBase3(EntityManagerFactoryBuilder builder) {
        return builder
                // 设置数据源
                .dataSource(dataBase3DataSource)
                //设置实体类所在位置.扫描所有带有 @Entity 注解的类
                .packages("com.hui.demo.entity.dataBase3")
                // Spring会将EntityManagerFactory注入到Repository之中.有了 EntityManagerFactory之后,
                // Repository就能用它来创建 EntityManager 了,然后 EntityManager 就可以针对数据库执行操作
                .persistenceUnit("dataBase3PersistenceUnit")
                .build();
    }

    /**
     * 配置事物管理器
     *
     * @param builder
     * @return
     */
    @Bean(name = "transactionManagerDataBase3")
    PlatformTransactionManager transactionManagerDataBase3(EntityManagerFactoryBuilder builder) {
        return new JpaTransactionManager(entityManagerFactoryDataBase3(builder).getObject());
    }
}

@Primary的意思是在众多相同的bean中,优先使用用@Primary注解的bean.而@Qualifier这个注解则指定某个bean有没有资格进行注入。

此时,多数据源的主要配置已经完成,下面是一些实体类、dao的常用配置

5、配置实体类,dao

在User、Student、User、UserDaoRepository、StudentDaoRepository、UsertDaoRepository六个类中分别配置如下:

package com.hui.demo.entity.database1;

import lombok.Data;
import javax.persistence.*;

@Entity
@Table(name = "tbl_user")
@Data
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    private String name;

    private String password;
}
package com.hui.demo.dao.database1;

import com.hui.demo.entity.database1.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.stereotype.Repository;

@Repository
public interface UserDaoRepository extends JpaRepository<User, Integer>, JpaSpecificationExecutor<User> {
}
package com.hui.demo.entity.database2;

import lombok.Data;

import javax.persistence.*;

@Entity
@Table(name = "tbl_student")
@Data
public class Student {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    private String name;

    private String grade;
}
package com.hui.demo.dao.database2;

import com.hui.demo.entity.database2.Student;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.stereotype.Repository;

@Repository
public interface StudentDaoRepository extends JpaRepository<Student, Integer>, JpaSpecificationExecutor<Student> {
}
package com.hui.demo.entity.database3;

import lombok.Data;

import javax.persistence.*;

@Entity
@Table(name = "tbl_user")
@Data
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    private String name;

    private String password;
}

注意:虽然表结构表名都一样,但是不能和上面的UserDaoRepository名称一样,所以这里改成了UsertDaoRepository

package com.hui.demo.dao.database3;

import com.hui.demo.entity.database3.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.stereotype.Repository;

@Repository
// 名称不能和UserDaoRepository重复,虽然是同库同表
public interface UsertDaoRepository extends JpaRepository<User, Integer>, JpaSpecificationExecutor<User> {
}
6、maven文件配置
<?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.guoxin</groupId>
    <artifactId>SpringbootTest</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.4.RELEASE</version>
        <relativePath/>
    </parent>

    <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-data-jpa</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>

<!--        <dependency>-->
<!--            <groupId>com.microsoft.sqlserver</groupId>-->
<!--            <artifactId>sqljdbc4</artifactId>-->
<!--            <version>4.0</version>-->
<!--        </dependency>-->

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.9</version>
        </dependency>
    </dependencies>

    <build>
        <finalName>SpringBootTest</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
7、数据库配置
CREATE TABLE `tbl_user` (
  `id` int(10),
  `name` VARCHAR(255),
  `password` VARCHAR(200)
) ENGINE=INNODB DEFAULT CHARSET=utf8;

INSERT into tbl_user(id,name,password) VALUES("1","张三","123456");
INSERT into tbl_user(id,name,password) VALUES("2","王五","654321");

分别创建两个数据库database1、database2,database3,database1中创建tbl_user表,database2中创建tbl_student表,database3中创建tbl_user表,如下图:
在这里插入图片描述

8、接口实现

在TestController.java中添加接口访问:

package com.hui.demo.web;

import com.hui.demo.dao.database1.UserDaoRepository;
import com.hui.demo.dao.database2.StudentDaoRepository;
import com.hui.demo.entity.database2.Student;
import com.hui.demo.entity.database1.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Map;

@RestController
public class TestController {

    @Autowired
    private UserDaoRepository userDaoRepository;

    @Autowired
    private StudentDaoRepository studentDaoRepository;

    @Autowired
    JdbcTemplate jdbcTemplate;

    @GetMapping(value = "/getuser")
    public List<User> getuser(){
        List<User> all = userDaoRepository.findAll();
        return all;
    }

    @GetMapping(value = "/getstudent")
    public List<Student> getstudent(){
        List<Student> all = studentDaoRepository.findAll();
        return all;
    }

    @ResponseBody
    @GetMapping("/query")
    public Map<String,Object> map(){
        List<Map<String, Object>> list = jdbcTemplate.queryForList("select * FROM tbl_user");
        return list.get(0);
    }
}

启动类:

package com.lss;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

@SpringBootApplication
@EnableScheduling
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

至此,所有的类都已经实现,启动项目,再浏览器输入url访问数据:
在这里插入图片描述

9、访问druid监控页面http://localhost:8080/druid/login.html

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
疑问:即使配置了“filters: stat”,“SQL监控”界面却监控不到SQL语句,目前不知道是什么原因
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/m0_37739193/article/details/113617776