學習Spring Boot:(二十四)多數據源配置與使用

前言

隨着業務量增大,可能有些業務不是放在同一個數據庫中,因此係統有需求使用多個數據庫完成業務需求,咱們須要配置多個數據源,從而進行操做不一樣數據庫中數據。css

正文

JdbcTemplate 多數據源

配置

須要在 Spring Boot 中配置多個數據庫鏈接,固然怎麼設置鏈接參數的 key 能夠本身決定,java

須要注意的是 Spring Boot 2.0 的默認鏈接池配置參數好像有點問題,因爲默認鏈接池已從 Tomcat 更改成 HikariCP,之前有一個參數 url,已經改爲 hikari.jdbcUrl ,否則沒法註冊。我下面使用的版本是 1.5.9mysql

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
註冊 DataSource

註冊兩個數據源,分別註冊兩個 JdbcTemplategit

@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);
    }
}
測試
@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)));
    }
}

源碼地址github

使用 JPA 支持多數據源

配置

相比使用 jdbcTemplate,須要設置下 JPA 的相關參數便可,沒多大變化:spring

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

首先同樣的是咱們要註冊相應的 DataSource,還須要指定相應的數據源所對應的實體類和數據操做層 Repository的位置:
* firstDataSourcesql

@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());
    }

}
測試
@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))));
    }
}

源碼地址數據庫

相關文章
相關標籤/搜索