SpringBoot 配置多数据源的笔记总结.
首先,通过 spring initializr 新建一个Spring Boot项目. 为了方便,选择H2作为我们的数据库,选择web, h2, lombok等几个依赖,生成我们的Spring Boot项目.
默认情况下,Spring Boot 会帮我们自动装配
- DataSourceAutoConfiguration.class,
- JdbcTemplateAutoConfiguration.class,
- DataSourceTransactionManagerAutoConfiguration.class
这三个类数据源相关的类,为了配置多个数据源,我们需要手动排除掉Spring Boot为我们自动配置的类,同时我们自己手动配置了两个数据源,分别命名为 foo 和 bar, 相关代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
| @Slf4j @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, JdbcTemplateAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class}) // 排除掉Spring boot自动装配的类 public class DatasourceDemoApplication {
public static void main(String[] args) { SpringApplication.run(DatasourceDemoApplication.class, args); }
@Bean @ConfigurationProperties("bar.datasource") public DataSourceProperties barDatasourceProp() { return new DataSourceProperties(); }
@Bean @ConfigurationProperties("foo.datasource") public DataSourceProperties fooDatasourceProp() { return new DataSourceProperties(); }
@Bean public DataSource barDatasource() { DataSourceProperties dsProp = barDatasourceProp(); log.info("bar ds url:{}", dsProp.getUrl()); return dsProp.initializeDataSourceBuilder().build(); }
@Bean public DataSource fooDatasource() { DataSourceProperties dsProp = fooDatasourceProp(); log.info("foo ds url:{}", dsProp.getUrl()); return dsProp.initializeDataSourceBuilder().build(); }
@Bean public JdbcTemplate fooJdbcTemplate() { DataSource foo = fooDatasource(); return new JdbcTemplate(foo); }
@Bean public JdbcTemplate barJdbcTemplate() { DataSource bar = barDatasource(); return new JdbcTemplate(bar); }
@Bean public DataSourceTransactionManager barTxManager() { return new DataSourceTransactionManager(barDatasource()); }
@Bean public DataSourceTransactionManager fooTxManager() { return new DataSourceTransactionManager(fooDatasource()); } }
|
相应的配置文件application.properties配置项:
1 2 3 4 5 6 7
| foo.datasource.url=jdbc:h2:mem:foo foo.datasource.username=sa foo.datasource.password=
bar.datasource.url=jdbc:h2:mem:bar bar.datasource.username=sa bar.datasource.password=
|
之后我们可以写个测试类测试一下,我这里用的是一个Controller类,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
| import lombok.extern.slf4j.Slf4j; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource; import javax.sql.DataSource; import java.sql.*;
@RestController @RequestMapping("ds") @Slf4j public class DataSourceDemoController {
@Resource(name="fooDatasource") DataSource fooDS;
@Resource(name="barDatasource") DataSource barDS;
@Resource(name="fooJdbcTemplate") JdbcTemplate fooJdbc;
@Resource(name="barJdbcTemplate") JdbcTemplate barJdbc;
@PostMapping("fooInsert") public String insertDataWithFoo() { try { String sql = "INSERT INTO USER (name) VALUES ('foo')"; fooJdbc.execute(sql); } catch (Exception e) { log.error("error:{}", e.getMessage()); }
return "success"; }
@PostMapping("createTable") public String createTable() { Connection conn = null; try { conn = fooDS.getConnection(); log.info("conn:{}", conn); Statement stmt = conn.createStatement(); stmt.execute("DROP TABLE IF EXISTS `USER`"); stmt.execute("CREATE TABLE `USER` (id INTEGER PRIMARY KEY AUTO_INCREMENT, name VARCHAR(100));");
} catch (SQLException e) { log.error("errors occur when creating table:{} ", e.getMessage()); } finally { if (conn != null) { try { conn.close(); } catch (SQLException e) { log.error("exception occurs: ", e); } } } return "success"; }
@GetMapping("barSelect") public String selectDataWithBar() {
try { barJdbc.queryForList("SELECT * FROM `USER`").forEach(row -> System.out.println(row)); } catch (Exception e) { return e.getMessage(); } return "success"; }
@GetMapping("fooSelect") public String selectDataWithFoo() { try { fooJdbc.queryForList("SELECT * FROM `USER`").forEach(row -> System.out.println(row)); } catch (Exception e) { return e.getMessage(); } return "success"; }
}
|
通过访问 /ds/createTable 先在 foo 数据源新建一个USER 表, 再通过 /ds/fooInsert 插入一条数据。通过访问 /ds/barSelect 会发现返回 “==Table USER NOT EXIST==“ 这样的报错,说明我们刚刚的 USER表确实是来自于 foo 数据源而不是 bar 数据源。 最后通过 /ds/fooSelect 查询一下刚刚插入进去的记录,发现确实是插入成功的。由此证明了我们刚刚确实是配置了两个数据源,而且通过这两个数据源确实也访问到了来源不同的数据。
以上