1 介绍

  • 使用JPA的配置两个数据库,配置不同的数据库。

    2 示例

    2.1 依赖引入

    注意:pom不要去改,引入其他druid会报错的!

    1. <parent>
    2. <groupId>org.springframework.boot</groupId>
    3. <artifactId>spring-boot-starter-parent</artifactId>
    4. <version>2.1.3.RELEASE</version>
    5. <relativePath/> <!-- lookup parent from repository -->
    6. </parent>
    7. <dependencies>
    8. <dependency>
    9. <groupId>org.springframework.boot</groupId>
    10. <artifactId>spring-boot-starter-web</artifactId>
    11. </dependency>
    12. <dependency>
    13. <groupId>org.springframework.boot</groupId>
    14. <artifactId>spring-boot-starter-data-jpa</artifactId>
    15. </dependency>
    16. <dependency>
    17. <groupId>org.springframework.boot</groupId>
    18. <artifactId>spring-boot-starter-actuator</artifactId>
    19. </dependency>
    20. <dependency>
    21. <groupId>mysql</groupId>
    22. <artifactId>mysql-connector-java</artifactId>
    23. </dependency>
    24. <dependency>
    25. <groupId>org.projectlombok</groupId>
    26. <artifactId>lombok</artifactId>
    27. <scope>provided</scope>
    28. </dependency>
    29. <dependency>
    30. <groupId>org.springframework.boot</groupId>
    31. <artifactId>spring-boot-starter-test</artifactId>
    32. <scope>test</scope>
    33. </dependency>
    34. <dependency>
    35. <groupId>com.alibaba</groupId>
    36. <artifactId>druid</artifactId>
    37. <version>1.1.9</version>
    38. </dependency>
    39. <dependency>
    40. <groupId>log4j</groupId>
    41. <artifactId>log4j</artifactId>
    42. <version>1.2.17</version>
    43. </dependency>
    44. </dependencies>

    2.2 自定义配置两个数据库

    application.yml

    1. spring:
    2. datasource:
    3. primary:
    4. url: jdbc:mysql://localhost:3306/primary?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true
    5. username: root
    6. password: 123456
    7. driver-class-name: com.mysql.cj.jdbc.Driver
    8. secondary:
    9. url: jdbc:mysql://localhost:3306/second?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true
    10. username: root
    11. password: 123456
    12. driver-class-name: com.mysql.cj.jdbc.Driver
    13. jpa:
    14. database: mysql
    15. generate-ddl: true
    16. show-sql: true
    17. hibernate:
    18. ddl-auto: update
    19. naming:
    20. physical-strategy: org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy

    2.3 配置默认的数据库源

    ```java package com.hikktn.config;

import com.alibaba.druid.pool.DruidDataSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; 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.stereotype.Component;

import javax.sql.DataSource; import java.sql.SQLException;

@Component @Configuration public class DataSourceConfig {

  1. private Logger logger = LoggerFactory.getLogger(DataSourceConfig.class);
  2. @Value("${spring.datasource.primary.url}")
  3. private String dbUrl1;
  4. @Value("${spring.datasource.primary.username}")
  5. private String username1;
  6. @Value("${spring.datasource.primary.password}")
  7. private String password1;
  8. @Value("${spring.datasource.secondary.username}")
  9. private String username2;
  10. @Value("${spring.datasource.secondary.password}")
  11. private String password2;
  12. @Value("${spring.datasource.secondary.url}")
  13. private String dbUrl2;
  14. @Value("${spring.datasource.secondary.driver-class-name}")
  15. private String driverClassName;
  16. @Value("5")
  17. private int initialSize;
  18. @Value("5")
  19. private int minIdle;
  20. @Value("20")
  21. private int maxActive;
  22. @Value("60000")
  23. private int maxWait;
  24. /**
  25. * 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
  26. */
  27. @Value("60000")
  28. private int timeBetweenEvictionRunsMillis;
  29. /**
  30. * 配置一个连接在池中最小生存的时间,单位是毫秒
  31. */
  32. @Value("300000")
  33. private int minEvictableIdleTimeMillis;
  34. @Value("SELECT 1 FROM DUAL")
  35. private String validationQuery;
  36. @Value("true")
  37. private boolean testWhileIdle;
  38. @Value("false")
  39. private boolean testOnBorrow;
  40. @Value("false")
  41. private boolean testOnReturn;
  42. /**
  43. * 打开PSCache,并且指定每个连接上PSCache的大小
  44. */
  45. @Value("true")
  46. private boolean poolPreparedStatements;
  47. @Value("20")
  48. private int maxPoolPreparedStatementPerConnectionSize;
  49. /**
  50. * 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
  51. */
  52. @Value("stat,wall,log4j")
  53. private String filters;
  54. /**
  55. * 通过connectProperties属性来打开mergeSql功能;慢SQL记录
  56. */
  57. @Value("druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500")
  58. private String connectionProperties;
  59. @Bean(name = "primaryDataSource")
  60. @Qualifier("primaryDataSource")
  61. public DataSource dataSource() {
  62. return getDruidDataSource(username1, password1, dbUrl1);
  63. }
  64. @Bean(name = "secondDataSource")
  65. @Qualifier("secondDataSource")
  66. @Primary
  67. public DataSource secondaryDataSource() {
  68. return getDruidDataSource(username2, password2, dbUrl2);
  69. }
  70. private DruidDataSource getDruidDataSource(String username, String password, String url) {
  71. DruidDataSource datasource = new DruidDataSource();
  72. datasource.setUrl(url);
  73. datasource.setUsername(username);
  74. datasource.setPassword(password);
  75. datasource.setDriverClassName(driverClassName);
  76. //configuration
  77. datasource.setInitialSize(initialSize);
  78. datasource.setMinIdle(minIdle);
  79. datasource.setMaxActive(maxActive);
  80. datasource.setMaxWait(maxWait);
  81. datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
  82. datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
  83. datasource.setValidationQuery(validationQuery);
  84. datasource.setTestWhileIdle(testWhileIdle);
  85. datasource.setTestOnBorrow(testOnBorrow);
  86. datasource.setTestOnReturn(testOnReturn);
  87. datasource.setPoolPreparedStatements(poolPreparedStatements);
  88. datasource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);
  89. try {
  90. datasource.setFilters(filters);
  91. } catch (SQLException e) {
  92. logger.error("druid configuration initialization filter : {0}", e);
  93. }
  94. datasource.setConnectionProperties(connectionProperties);
  95. return datasource;
  96. }

}

  1. <a name="pIgz2"></a>
  2. ## 2.4 JPA配置主数据库
  3. ```java
  4. package com.hikktn.config;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.beans.factory.annotation.Qualifier;
  7. import org.springframework.boot.autoconfigure.domain.EntityScan;
  8. import org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties;
  9. import org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings;
  10. import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
  11. import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
  12. import org.springframework.context.annotation.Bean;
  13. import org.springframework.context.annotation.Configuration;
  14. import org.springframework.context.annotation.Primary;
  15. import org.springframework.core.env.Environment;
  16. import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
  17. import org.springframework.orm.jpa.JpaTransactionManager;
  18. import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
  19. import org.springframework.transaction.PlatformTransactionManager;
  20. import org.springframework.transaction.annotation.EnableTransactionManagement;
  21. import javax.persistence.EntityManager;
  22. import javax.sql.DataSource;
  23. import java.util.Map;
  24. @Configuration
  25. @EnableTransactionManagement
  26. @EntityScan(basePackages = "com.hikktn.domain.primary")
  27. @EnableJpaRepositories(
  28. entityManagerFactoryRef = "entityManagerFactoryPrimary",
  29. transactionManagerRef = "transactionManagerPrimary",
  30. basePackages = {"com.hikktn.dao.primary"})
  31. public class PrimaryConfig {
  32. @Autowired
  33. @Qualifier("primaryDataSource")
  34. private DataSource primaryDataSource;
  35. @Autowired
  36. private JpaProperties jpaProperties;
  37. @Autowired
  38. private HibernateProperties hibernateProperties;
  39. private Map<String, Object> getVendorProperties() {
  40. return hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(), new HibernateSettings());
  41. }
  42. @Primary
  43. @Bean(name = "entityManagerPrimary")
  44. public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
  45. return entityManagerFactoryPrimary(builder).getObject().createEntityManager();
  46. }
  47. @Primary
  48. @Bean(name = "entityManagerFactoryPrimary")
  49. public LocalContainerEntityManagerFactoryBean entityManagerFactoryPrimary(EntityManagerFactoryBuilder builder) {
  50. return builder
  51. .dataSource(primaryDataSource)
  52. .properties(getVendorProperties())
  53. .packages("com.hikktn.domain.primary")
  54. .persistenceUnit("primaryPersistenceUnit")
  55. .build();
  56. }
  57. @Primary
  58. @Bean(name = "transactionManagerPrimary")
  59. public PlatformTransactionManager transactionManagerPrimary(EntityManagerFactoryBuilder builder) {
  60. return new JpaTransactionManager(entityManagerFactoryPrimary(builder).getObject());
  61. }
  62. }

2.5 JPA配置副数据库

  1. package com.hikktn.config;
  2. import org.springframework.beans.factory.annotation.Autowired;
  3. import org.springframework.beans.factory.annotation.Qualifier;
  4. import org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties;
  5. import org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings;
  6. import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
  7. import org.springframework.context.annotation.Bean;
  8. import org.springframework.context.annotation.Configuration;
  9. import org.springframework.core.env.Environment;
  10. import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
  11. import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
  12. import org.springframework.orm.jpa.JpaTransactionManager;
  13. import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
  14. import org.springframework.transaction.PlatformTransactionManager;
  15. import org.springframework.transaction.annotation.EnableTransactionManagement;
  16. import javax.annotation.Resource;
  17. import javax.persistence.EntityManager;
  18. import javax.sql.DataSource;
  19. import java.util.HashMap;
  20. import java.util.Map;
  21. @Configuration
  22. @EnableTransactionManagement
  23. @EnableJpaRepositories(
  24. //实体管理
  25. entityManagerFactoryRef="entityManagerFactorySecond",
  26. //事务管理
  27. transactionManagerRef="transactionManagerSecond",
  28. //实体扫描,设置Repository所在位置
  29. basePackages= { "com.hikktn.dao.second" })
  30. public class SecondConfig {
  31. @Autowired
  32. @Qualifier("secondDataSource")
  33. private DataSource secondDataSource;
  34. @Autowired
  35. private JpaProperties jpaProperties;
  36. @Autowired
  37. private HibernateProperties hibernateProperties;
  38. private Map<String, Object> getVendorProperties() {
  39. return hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(), new HibernateSettings());
  40. }
  41. @Bean(name = "entityManagerSecond")
  42. public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
  43. return entityManagerFactorySecond(builder).getObject().createEntityManager();
  44. }
  45. @Bean(name = "entityManagerFactorySecond")
  46. public LocalContainerEntityManagerFactoryBean entityManagerFactorySecond (EntityManagerFactoryBuilder builder) {
  47. return builder
  48. .dataSource(secondDataSource)
  49. .properties(getVendorProperties())
  50. .packages("com.hikktn.domain.second")
  51. .persistenceUnit("secondPersistenceUnit")
  52. .build();
  53. }
  54. @Bean(name = "transactionManagerSecond")
  55. PlatformTransactionManager transactionManagerSecond(EntityManagerFactoryBuilder builder) {
  56. return new JpaTransactionManager(entityManagerFactorySecond(builder).getObject());
  57. }
  58. }

2.6 主数据库Bean

  1. package com.hikktn.domain.primary;
  2. import lombok.AllArgsConstructor;
  3. import lombok.Data;
  4. import lombok.NoArgsConstructor;
  5. import javax.persistence.*;
  6. import java.io.Serializable;
  7. @Data
  8. @Entity
  9. @NoArgsConstructor
  10. @AllArgsConstructor
  11. @Table(name = "t_user")
  12. public class UserPrimaryEntity implements Serializable {
  13. @Id
  14. @GeneratedValue(strategy = GenerationType.IDENTITY)
  15. Long id;
  16. /**
  17. * 名称
  18. */
  19. String name;
  20. /**
  21. * 性别
  22. */
  23. String sex;
  24. }

2.7 副数据库Bean

  1. package com.hikktn.domain.second;
  2. import lombok.AllArgsConstructor;
  3. import lombok.Data;
  4. import lombok.NoArgsConstructor;
  5. import javax.persistence.*;
  6. import java.io.Serializable;
  7. @Data
  8. @Entity
  9. @NoArgsConstructor
  10. @AllArgsConstructor
  11. @Table(name = "t_user")
  12. public class UserSecondEntity implements Serializable {
  13. @Id
  14. @GeneratedValue(strategy = GenerationType.IDENTITY)
  15. Long id;
  16. /**
  17. * 名称
  18. */
  19. String name;
  20. /**
  21. * 性别
  22. */
  23. String sex;
  24. }

2.8 DAO层

  1. package com.hikktn.dao.primary;
  2. import com.hikktn.domain.primary.UserPrimaryEntity;
  3. import org.springframework.data.jpa.repository.JpaRepository;
  4. import org.springframework.stereotype.Repository;
  5. @Repository
  6. public interface UserPrimaryRepository extends JpaRepository<UserPrimaryEntity, Long> {
  7. }
  1. package com.hikktn.dao.second;
  2. import com.hikktn.domain.second.UserSecondEntity;
  3. import org.springframework.data.jpa.repository.JpaRepository;
  4. import org.springframework.stereotype.Repository;
  5. @Repository
  6. public interface UserSecondRepository extends JpaRepository<UserSecondEntity, Long> {
  7. }

2.9 启动类

  1. package com.hikktn;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. @SpringBootApplication
  5. public class Application {
  6. public static void main(String[] args) {
  7. SpringApplication.run(Application.class, args);
  8. }
  9. }

2.10 测试

  1. import com.hikktn.Application;
  2. import com.hikktn.dao.primary.UserPrimaryRepository;
  3. import com.hikktn.dao.second.UserSecondRepository;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.boot.test.context.SpringBootTest;
  6. import org.junit.Test;
  7. import org.junit.runner.RunWith;
  8. import org.springframework.test.context.junit4.SpringRunner;
  9. @RunWith(SpringRunner.class)
  10. @SpringBootTest(classes = Application.class)
  11. public class SpringbootJapDatasourceApplicationTests {
  12. @Autowired
  13. private UserPrimaryRepository userPrimaryRepository;
  14. @Autowired
  15. private UserSecondRepository userSecondRepository;
  16. @Test
  17. public void contextLoads() {
  18. System.out.println(userPrimaryRepository.findAll());
  19. System.out.println(userSecondRepository.findAll());
  20. }
  21. }
  • 数据库里的数据

image.png

  • 结果
    1. Hibernate: select userprimar0_.id as id1_0_, userprimar0_.name as name2_0_, userprimar0_.sex as sex3_0_ from t_user userprimar0_
    2. [UserPrimaryEntity(id=1, name=zhansan, sex=男), UserPrimaryEntity(id=2, name=tom, sex=男)]
    3. 2021-08-31 23:44:44.991 INFO 16516 --- [ main] o.h.h.i.QueryTranslatorFactoryInitiator : HHH000397: Using ASTQueryTranslatorFactory
    4. Hibernate: select usersecond0_.id as id1_0_, usersecond0_.name as name2_0_, usersecond0_.sex as sex3_0_ from t_user usersecond0_
    5. [UserSecondEntity(id=1, name=kitty, sex=女)]