Learning Spring Boot: (24) Configuration and Use of Multiple Data Sources

foreword

As the business volume increases, some businesses may not be placed in the same database, so the system needs to use multiple databases to fulfill business requirements. We need to configure multiple data sources to operate data in different databases.

text

JdbcTemplate Multiple Data Sources

configure

You need to configure multiple database connections in Spring Boot. Of course, you can decide how to set the key of connection parameters.

It should be noted that there seems to be a problem with Spring Boot 2.0the default connection pool configuration parameters of . Since the default connection pool has been Tomcatchanged from to HikariCP, there was a parameter before url, which has been changed hikari.jdbcUrl, otherwise it cannot be registered. The version I'm using below is 1.5.9.

server:
  port: 8022
spring:
  datasource:
     url: jdbc:mysql://localhost:3306/learn?useSSL=false&allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8
     username: root
     password: 123456
     driver-class-name: com.mysql.jdbc.Driver

  second-datasource:
    url: jdbc:mysql://localhost:3306/learn1?useSSL=false&allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8
    username: root
    password: 123457
    driver-class-name: com.mysql.jdbc.Driver
Register DataSource

Register two data sources, register two respectively JdbcTemplate,

@Configuration
public class DataSourceConfig {

    /**
     * 注册 data source
     *
     * @return
     */
    @ConfigurationProperties(prefix = "spring.datasource")
    @Bean("firstDataSource")
    @Primary // 有相同实例优先选择
    public DataSource firstDataSource() {
        return DataSourceBuilder.create().build();
    }

    @ConfigurationProperties(prefix = "spring.second-datasource")
    @Bean("secondDataSource")
    public DataSource secondDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean("firstJdbcTemplate")
    @Primary
    public JdbcTemplate firstJdbcTemplate(DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }

    @Bean("secondJdbcTemplate")
    public JdbcTemplate secondJdbcTemplate(@Qualifier("secondDataSource") DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }
}
test
@SpringBootTest
@RunWith(SpringRunner.class)
public class TestJDBC {
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Autowired
    @Qualifier("secondJdbcTemplate")
    private JdbcTemplate jdbcTemplate1;

    @Before
    public void before() {
        jdbcTemplate.update("DELETE FROM employee");
        jdbcTemplate1.update("DELETE FROM employee");
    }

    @Test
    public void testJDBC() {
        jdbcTemplate.update("insert into employee(id,name,age) VALUES (1, 'wuwii', 24)");
        jdbcTemplate1.update("insert into employee(id,name,age) VALUES (1, 'kronchan', 23)");
        Assert.assertThat("wuwii", Matchers.equalTo(jdbcTemplate.queryForObject("SELECT name FROM employee WHERE id=1", String.class)));
        Assert.assertThat("kronchan", Matchers.equalTo(jdbcTemplate1.queryForObject("SELECT name FROM employee WHERE id=1", String.class)));
    }
}

Source address

Using JPA to support multiple data sources

configure

Compared with the use jdbcTemplate, you need to set JPAthe , and there is not much change:

server:
  port: 8022
spring:
  datasource:
     url: jdbc:mysql://localhost:3306/learn?useSSL=false&allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8
     username: root
     password: 123456
     driver-class-name: com.mysql.jdbc.Driver

  second-datasource:
    url: jdbc:mysql://localhost:3306/learn1?useSSL=false&allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8
    username: root
    password: 123456
    driver-class-name: com.mysql.jdbc.Driver

  jpa:
    show-sql: true
    database: mysql
    hibernate:
    # update 更新表结构
    # create 每次启动删除上次表,再创建表,会造成数据丢失
    # create-drop: 每次加载hibernate时根据model类生成表,但是sessionFactory一关闭,表就自动删除。
    # validate :每次加载hibernate时,验证创建数据库表结构,只会和数据库中的表进行比较,不会创建新表,但是会插入新值。
      ddl-auto: update
    properties:
      hibernate:
        dialect: org.hibernate.dialect.MySQLDialect

The first thing is that we need to register the corresponding DataSource, and also need to specify Repositorythe :
*firstDataSource

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef = "firstEntityManagerFactory",
        transactionManagerRef = "firstTransactionManager",
        basePackages = "com.wuwii.module.system.dao" // 设置该数据源对应 dao 层所在的位置
)
public class FirstDataSourceConfig {

    @Autowired
    private JpaProperties jpaProperties;
    @Primary
    @Bean(name = "firstEntityManager")
    public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
        return entityManagerFactoryPrimary(builder).getObject().createEntityManager();
    }

    @ConfigurationProperties(prefix = "spring.datasource")
    @Bean("firstDataSource")
    @Primary // 有相同实例优先选择,相同实例只能设置唯一
    public DataSource firstDataSource() {
        return DataSourceBuilder.create().build();
    }
    @Primary
    @Bean(name = "firstEntityManagerFactory")
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryPrimary (EntityManagerFactoryBuilder builder) {
        return builder
                .dataSource(firstDataSource())
                .properties(getVendorProperties(firstDataSource()))
                .packages("com.wuwii.module.system.entity") //设置该数据源对应的实体类所在位置
                .persistenceUnit("firstPersistenceUnit")
                .build();
    }

    private Map<String, String> getVendorProperties(DataSource dataSource) {
        return jpaProperties.getHibernateProperties(dataSource);
    }

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

}
  • secondDataSource
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
        entityManagerFactoryRef = "secondEntityManagerFactory",
        transactionManagerRef = "secondTransactionManager",
        basePackages = "com.wuwii.module.user.dao" // 设置该数据源 dao 层所在的位置
)
public class SecondDataSourceConfig {

    @Autowired
    private JpaProperties jpaProperties;
    @Bean(name = "secondEntityManager")
    public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
        return entityManagerFactoryPrimary(builder).getObject().createEntityManager();
    }


    @ConfigurationProperties(prefix = "spring.second-datasource")
    @Bean("secondDataSource")
    public DataSource secondDataSource() {
        return DataSourceBuilder.create().build();
    }
    @Bean(name = "secondEntityManagerFactory")
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryPrimary (EntityManagerFactoryBuilder builder) {
        return builder
                .dataSource(secondDataSource())
                .properties(getVendorProperties(secondDataSource()))
                .packages("com.wuwii.module.user.entity") //设置该数据源锁对应的实体类所在的位置
                .persistenceUnit("secondPersistenceUnit")
                .build();
    }

    private Map<String, String> getVendorProperties(DataSource dataSource) {
        return jpaProperties.getHibernateProperties(dataSource);
    }

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

}
test
@SpringBootTest
@RunWith(SpringRunner.class)
public class TestDemo {
    @Autowired
    private EmployeeDao employeeDao;
    @Autowired
    private UserDao userDao;
    @Before
    public void before() {
        employeeDao.deleteAll();
        userDao.deleteAll();
    }

    @Test
    public void test() {
        Employee employee = new Employee(null, "wuwii", 24);
        employeeDao.save(employee);
        User user = new User(null, "KronChan", 24);
        userDao.save(user);
        Assert.assertThat(employee, Matchers.equalTo(employeeDao.findOne(Example.of(employee))));
        Assert.assertThat(user, Matchers.equalTo(userDao.findOne(Example.of(user))));
    }
}

Source address

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325724037&siteId=291194637