Loading...

本篇文章采用 Springboot 整合 Hibernate 实现多数据源模式,数据库采用 postgresql。

# 引入需要的依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
    <version>2.2.6.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
    <version>2.2.6.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.postgresql</groupId>
    <artifactId>postgresql</artifactId>
    <version>42.2.14</version>
</dependency>

# 建表

以下两个数据表在不同的数据库中

构建第一数据源表

CREATE TABLE "public"."primary" (
  "id" int4 NOT NULL,
  "code" varchar(255) COLLATE "pg_catalog"."default",
  "name" varchar(255) COLLATE "pg_catalog"."default",
  CONSTRAINT "primary_pkey" PRIMARY KEY ("id")
)
;
ALTER TABLE "public"."primary" 
  OWNER TO "postgres";
  
-- 插入数据
INSERT INTO "public"."primary"("id", "code", "name") VALUES (1, 'PRIMARY', '第一数据源');

构建第二数据源表

CREATE TABLE "public"."second" (
  "id" int4 NOT NULL,
  "code" varchar(255) COLLATE "pg_catalog"."default",
  "name" varchar(255) COLLATE "pg_catalog"."default",
  CONSTRAINT "second_pkey" PRIMARY KEY ("id")
)
;
ALTER TABLE "public"."second" 
  OWNER TO "postgres";
  
-- 插入数据
INSERT INTO "public"."second"("id", "code", "name") VALUES (1, 'SECOND', '第二数据源');

# 配置文件

server:
  port: 8080
spring:
  datasource:
    primary:
      driver-class-name: org.postgresql.Driver
      jdbc-url: jdbc:postgresql://127.0.0.1:5432/primary
      username: xxx
      password: xxx
      hikari:
      minimum-idle: 2
    second:
      driver-class-name: org.postgresql.Driver
      jdbc-url: jdbc:postgresql://127.0.0.1:5432/second
      username: xxx
      password: xxx
      hikari:
      minimum-idle: 2
  jpa:
    hibernate:
      ddl-auto: none
      show-sql: true

# 多数据源配置

第一数据源配置

PrimaryConfig

package com.example.demo.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
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.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
/**
 * 在 com.example.demo.dao.primary 这个包下
 * 都访问第一数据源
 */
@Configuration
@EnableJpaRepositories(basePackages = {"com.example.demo.dao.primary"},
	transactionManagerRef = "primaryJpaTransactionManager", 
	entityManagerFactoryRef = "primaryLocalContainerEntityManagerFactoryBean")
@EnableTransactionManagement
public class PrimaryConfig {
    @Value("${spring.jpa.hibernate.show-sql}")
    private boolean showSql;
    
    @Primary
    @Bean(destroyMethod = "", name = "primaryEntityManager")
    public EntityManager primaryEntityManager(@Qualifier(value = "primaryDataSource") DataSource dataSource) {
        return primaryLocalContainerEntityManagerFactoryBean(dataSource).getObject().createEntityManager();
    }	
    
    @Autowired
    @Primary
    @Bean(destroyMethod = "", name = "primaryJpaTransactionManager")
    public JpaTransactionManager primaryJpaTransactionManager(
	    @Qualifier(value = "primaryDataSource") DataSource dataSource,
	    @Qualifier("primaryLocalContainerEntityManagerFactoryBean") EntityManagerFactory entityManagerFactory) {
        JpaTransactionManager primaryJpaTransactionManager = new JpaTransactionManager();
        primaryJpaTransactionManager.setEntityManagerFactory(entityManagerFactory);
        primaryJpaTransactionManager.setDataSource(dataSource);
        return primaryJpaTransactionManager;
    }
    @Autowired
    @Primary
    @Bean(destroyMethod = "", name = "primaryLocalContainerEntityManagerFactoryBean")
    LocalContainerEntityManagerFactoryBean primaryLocalContainerEntityManagerFactoryBean(
	    @Qualifier(value = "primaryDataSource") DataSource dataSource) {
	LocalContainerEntityManagerFactoryBean primaryLocalContainerEntityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
        primaryLocalContainerEntityManagerFactoryBean.setDataSource(dataSource);
        // 扫描实体包
        primaryLocalContainerEntityManagerFactoryBean.setPackagesToScan("com.example.demo.entity");
        // 可扫描多个
//        primaryLocalContainerEntityManagerFactoryBean.setPackagesToScan("com.example.demo.entity", "com.example.demo.xxx");
        primaryLocalContainerEntityManagerFactoryBean.setPersistenceUnitName("primaryPersistenceUnit");
        HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
        jpaVendorAdapter.setGenerateDdl(false);
        jpaVendorAdapter.setShowSql(showSql);
        primaryLocalContainerEntityManagerFactoryBean.setJpaVendorAdapter(jpaVendorAdapter);
        return primaryLocalContainerEntityManagerFactoryBean;
    }
}

第二数据源配置

SecondConfig

package com.example.demo.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
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.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
/**
 * 在 com.example.demo.dao.second 包下
 * 都访问第二数据源
 */
@Configuration
@EnableJpaRepositories(basePackages = "com.example.demo.dao.second",
        transactionManagerRef = "secondaryJpaTransactionManager",
        entityManagerFactoryRef = "secondaryLocalContainerEntityManagerFactoryBean")
@EnableTransactionManagement
public class SecondConfig {
    @Value("${spring.jpa.hibernate.show-sql}")
    private boolean showSql;
    @Bean(destroyMethod = "", name = "secondaryEntityManager")
    public EntityManager secondaryEntityManager(@Qualifier(value = "secondaryDataSource") DataSource dataSource) {
        return secondaryLocalContainerEntityManagerFactoryBean(dataSource).getObject().createEntityManager();
    }
    @Autowired
    @Bean(destroyMethod = "", name = "secondaryJpaTransactionManager")
    public JpaTransactionManager secondaryJpaTransactionManager(
            @Qualifier(value = "secondaryDataSource") DataSource dataSource,
            @Qualifier("secondaryLocalContainerEntityManagerFactoryBean") EntityManagerFactory entityManagerFactory) {
        JpaTransactionManager secondaryJpaTransactionManager = new JpaTransactionManager();
        secondaryJpaTransactionManager.setEntityManagerFactory(entityManagerFactory);
        secondaryJpaTransactionManager.setDataSource(dataSource);
        return secondaryJpaTransactionManager;
    }
    @Autowired
    @Bean(destroyMethod = "", name = "secondaryLocalContainerEntityManagerFactoryBean")
    LocalContainerEntityManagerFactoryBean secondaryLocalContainerEntityManagerFactoryBean(
            @Qualifier(value = "secondaryDataSource") DataSource dataSource) {
        LocalContainerEntityManagerFactoryBean secondaryLocalContainerEntityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
        secondaryLocalContainerEntityManagerFactoryBean.setDataSource(dataSource);
        // 扫描实体包
        secondaryLocalContainerEntityManagerFactoryBean.setPackagesToScan("com.example.demo.entity");
        secondaryLocalContainerEntityManagerFactoryBean.setPersistenceUnitName("secondaryPersistenceUnit");
        HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
        jpaVendorAdapter.setGenerateDdl(false);
        jpaVendorAdapter.setShowSql(showSql);
        secondaryLocalContainerEntityManagerFactoryBean.setJpaVendorAdapter(jpaVendorAdapter);
        return secondaryLocalContainerEntityManagerFactoryBean;
    }
}

总数据源配置

DataSourceConfig

package com.example.demo.config;
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;
import org.springframework.jdbc.core.JdbcTemplate;
import javax.sql.DataSource;
/**
 * 总数据源配置
 */
@Configuration
public class DataSourceConfig {
    @Bean(name = "primaryDataSource")
    @Qualifier("primaryDataSource")
    @Primary
    @ConfigurationProperties(prefix = "spring.datasource.primary")
    public DataSource primaryDataSource(){
        return DataSourceBuilder.create().build();
    }
    
    @Bean(name = "secondaryDataSource")
    @Qualifier("secondaryDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.second")
    public DataSource secondaryDataSource(){
   return DataSourceBuilder.create().build();
    }
    /**
     * TODO 还可配置多个
     */
    @Bean(name = "thirdDataSource")
    @Qualifier("thirdDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.third")
    public DataSource thirdDataSource(){
        return DataSourceBuilder.create().build();
    }
 
    @Bean(name = "secondaryJdbcTemplate")
    public JdbcTemplate secondaryJdbcTemplate(@Qualifier("secondaryDataSource")DataSource secondaryDataSource){
        return new JdbcTemplate(secondaryDataSource);
    }
    @Bean(name = "thirdJdbcTemplate")
    public JdbcTemplate thirdJdbcTemplate(@Qualifier("thirdDataSource")DataSource thirdDataSource){
        return new JdbcTemplate(thirdDataSource);
    }
}

# 实体层

第一实体

PrimaryEntity

package com.example.demo.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
@Table(schema = "public", name = "primary")
@Entity
public class PrimaryEntity {
    @Id
    @Column(name = "id")
    private String id;
    @Column(name = "name")
    private String name;
    @Column(name = "code")
    private String code;
    @Override
    public String toString() {
        return "PrimaryEntity{" +
                "id='" + id + '\'' +
                ", name='" + name + '\'' +
                ", code='" + code + '\'' +
                '}';
    }
}

第二实体

SecondEntity

package com.example.demo.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
@Table(schema = "public", name = "second")
@Entity
public class SecondEntity {
    @Id
    @Column(name = "id")
    private String id;
    @Column(name = "name")
    private String name;
    @Column(name = "code")
    private String code;
    @Override
    public String toString() {
        return "SecondEntity{" +
                "id='" + id + '\'' +
                ", name='" + name + '\'' +
                ", code='" + code + '\'' +
                '}';
    }
}

# DAO 层

第一数据源访问 DAO 层

在 com.example.demo.dao.primary 包下

PrimaryDao

package com.example.demo.dao.primary;
import com.example.demo.entity.PrimaryEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.stereotype.Repository;
@Repository
public interface PrimaryDao extends JpaSpecificationExecutor<PrimaryEntity>, JpaRepository<PrimaryEntity, String> {
}

第二数据源访问 DAO 层

在 com.example.demo.dao.second 包下

SecondDao

package com.example.demo.dao.second;
import com.example.demo.entity.SecondEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.stereotype.Repository;
@Repository
public interface SecondDao extends JpaSpecificationExecutor<SecondEntity>, JpaRepository<SecondEntity, String> {
    
}

# 启动类

package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.ComponentScan;
@SpringBootApplication
@ComponentScan(value = {
        "com.example.demo.dao",
        "com.example.demo.entity",
        "com.example.demo.config"
})
@EntityScan(value = {
        "com.example.demo.entity"
})
public class MainApplication {
    public static void main(String[] args) {
        SpringApplication.run(MainApplication.class, args);
    }
}

# 测试类

package com.example.demo;
import com.example.demo.dao.primary.PrimaryDao;
import com.example.demo.dao.second.SecondDao;
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 DemoTest {
    @Autowired
    private PrimaryDao primaryDao;
    
    @Autowired
    private SecondDao secondDao;
    @Test
    public void query(){
        //findAll 为 JPA 自带方法,查询所有
        System.out.println(primaryDao.findAll());
        System.out.println(secondDao.findAll());
    }
}

打印结果

Hibernate: select primaryent0_.id as id1_0_, primaryent0_.code as code2_0_, primaryent0_.name as name3_0_ from public.primary primaryent0_
[PrimaryEntity {id='1', name=' 第一数据源 ', code='PRIMARY'}]
Hibernate: select secondenti0_.id as id1_1_, secondenti0_.code as code2_1_, secondenti0_.name as name3_1_ from public.second secondenti0_
[SecondEntity {id='1', name=' 第二数据源 ', code='SECOND'}]

更新于

请我喝[茶]~( ̄▽ ̄)~*

七音 微信支付

微信支付

七音 支付宝

支付宝