具有多个数据源的Spring Boot 2

Spring Boot 2 with Multiple DataSource

有时候,即使拥有最好的数据库(PostgreSQL,Oracle,Sql等),调优也无法像应用程序级别那样将读写分开。

具有多个数据源的Spring Boot 2.2.2

Postgres Setup

对于此演示,您需要2个单独的Postgres数据库,其中一个作为Master,另一个作为副本。

为简单起见,只需运行:

docker-组成--force-recreate

的docker-compose.yml已经在包含2个不同端口的2个Postgresql的项目中,演示数据库

Note: you can always uninstall it as: docker-compose down if you needed to.
you can clone this project from my github on https://github.com/ehsaniara/spring-boot-multi-data-source

Spring Boot Setup

From https://start.spring.io/ select web, data-jpa, lombok, postgresDriver

生成并下载zip文件后,您应该拥有与以下类似的POM文件:


<dependencies>

   <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.springframework.boot</groupId>
      <artifactId>spring-boot-configuration-processor</artifactId>
   </dependency>

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

   <dependency>
      <groupId>org.postgresql</groupId>
      <artifactId>postgresql</artifactId>
      <scope>runtime</scope>
   </dependency>


</dependencies>

对于这个演示,我使用HikariDataSource作为Spring Boot 2.2.2的默认连接池库 我们需要有2个单独的DataSource和EntityManager,一个用于Writes(主服务器/主服务器),另一个用于Reads(从机服务器/第二服务器)。


spring:
  datasource-write:
    driver-class-name: org.postgresql.Driver
    jdbc-url: jdbc:postgresql://localhost:5432/demo
    username: 'postgres_user_for_db_write'
    password: 'you_password'
    platform: postgresql
    hikari:
      idle-timeout: 10000
      maximum-pool-size: 10
      minimum-idle: 5
      pool-name: WriteHikariPool

  datasource-read:
    driver-class-name: org.postgresql.Driver
    jdbc-url: jdbc:postgresql://localhost:5433/demo
    username: 'postgres_user_for_db_read'
    password: 'you_password'
    platform: postgresql
    hikari:
      idle-timeout: 10000
      maximum-pool-size: 10
      minimum-idle: 5
      pool-name: ReadHikariPool

如您所见,我有2个数据源,分别是:具有自己的凭据的datasource-write和datasource-read。

WriteDB的数据源配置:

@Configuration
@ConfigurationProperties("spring.datasource-write")
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef = "entityManagerFactoryWrite",
        transactionManagerRef = "transactionManagerWrite",
        basePackages = {"com.ehsaniara.multidatasource.repository.writeRepository"}
)
public class DataSourceConfigWrite extends HikariConfig {

    public final static String PERSISTENCE_UNIT_NAME = "write";

    @Bean
    public HikariDataSource dataSourceWrite() {
        return new HikariDataSource(this);
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryWrite(
            final HikariDataSource dataSourceWrite) {

        return new LocalContainerEntityManagerFactoryBean() {{
            setDataSource(dataSourceWrite);
            setPersistenceProviderClass(HibernatePersistenceProvider.class);
            setPersistenceUnitName(PERSISTENCE_UNIT_NAME);
            setPackagesToScan(MODEL_PACKAGE);
            setJpaProperties(JPA_PROPERTIES);
        }};
    }

    @Bean
    public PlatformTransactionManager transactionManagerWrite(EntityManagerFactory entityManagerFactoryWrite) {
        return new JpaTransactionManager(entityManagerFactoryWrite);
    }
}

ReadDB的数据源配置:

@Configuration
@ConfigurationProperties("spring.datasource-read")
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef = "entityManagerFactoryRead",
        transactionManagerRef = "transactionManagerRead",
        basePackages = {"com.ehsaniara.multidatasource.repository.readRepository"}
)
public class DataSourceConfigRead extends HikariConfig {

    public final static String PERSISTENCE_UNIT_NAME = "read";


    @Bean
    public HikariDataSource dataSourceRead() {
        return new HikariDataSource(this);
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryRead(
            final HikariDataSource dataSourceRead) {

        return new LocalContainerEntityManagerFactoryBean() {{
            setDataSource(dataSourceRead);
            setPersistenceProviderClass(HibernatePersistenceProvider.class);
            setPersistenceUnitName(PERSISTENCE_UNIT_NAME);
            setPackagesToScan(MODEL_PACKAGE);
            setJpaProperties(JPA_PROPERTIES);
        }};
    }

    @Bean
    public PlatformTransactionManager transactionManagerRead(EntityManagerFactory entityManagerFactoryRead) {
        return new JpaTransactionManager(entityManagerFactoryRead);
    }
}

读写存储库应放在单独的程序包中:

写:com.ehsaniara.multidatasource.repository.writeRepository

读:com.ehsaniara.multidatasource.repository.readRepository

您还需要设置:

public final static String MODEL_PACKAGE = "com.ehsaniara.multidatasource.model";

public final static Properties JPA_PROPERTIES = new Properties() {{
    put("hibernate.dialect", "org.hibernate.dialect.PostgreSQL10Dialect");
    put("hibernate.hbm2ddl.auto", "update");
    put("hibernate.ddl-auto", "update");
    put("show-sql", "true");
}};

和实际的逻辑在服务层中:

@Service
public class CustomerServiceImpl implements CustomerService {

    private final CustomerReadRepository customerReadRepository;
    private final CustomerWriteRepository customerWriteRepository;

    public CustomerServiceImpl(CustomerReadRepository customerReadRepository, CustomerWriteRepository customerWriteRepository) {
        this.customerReadRepository = customerReadRepository;
        this.customerWriteRepository = customerWriteRepository;
    }

    public Optional<Customer> getCustomer(Long id) {
        return customerReadRepository.findById(id);
    }

    public Customer createCustomer(Customer customer) {

        Assert.notNull(customer, "Invalid customer");
        Assert.isNull(customer.getId(), "customer id should be null");
        Assert.notNull(customer.getName(), "Invalid customer name");

        return customerWriteRepository.save(customer);
    }

    public Customer updateCustomer(Customer customer) {

        Assert.notNull(customer, "Invalid customer");
        Assert.notNull(customer.getId(), "Invalid customer id");

        return customerWriteRepository.save(customer);
    }
}

现在,如果运行此行,您将在DB1中创建客户:

curl -H "Content-Type: application/json" --request POST --data '{"name":"Jay"}'   http://localhost:8080/customer

要么

curl -H "Content-Type: application/json" --request PUT --data '{"id":1 , "name":"Jay ehsaniara"}'   http://localhost:8080/customer

但是,如果运行此行,则可以从DB2获取数据:

 curl --request GET  http://localhost:8080/customer/1

注意:您需要在DB2中手动插入客户,因为它没有前客户。 并且我们还没有设置Postgres Replication

from: https://dev.to//ehsaniara/spring-boot-2-with-multiple-datasources-1n9e

发布了0 篇原创文章 · 获赞 0 · 访问量 417

猜你喜欢

转载自blog.csdn.net/cunxiedian8614/article/details/105690009
今日推荐