前段时间公司要开发一套企业级的Saas系统,为了方便部署和迁移因此每个企业的数据库是独立的,数据库之间没有关联。库以及表动态创建的,只有用户注册后才会动态创建。
该功能实现起来比较简单,因为数据库是独立的,因此不需要考虑事务问题、跨库查询等分库分表的常见问题。但是因为因为云端部署多个数据库成本很高并且会造资源浪费,因此采用的是逻辑分库的方式及创建多个schema的方式进行分库。
我们目前使用的开发架构是springboot+mybatis,但是mybatis无法满足动态schema的需求,因此改用Springboot+SpringJDBC的方式。
主要的依赖如下:
com.zaxxer
HikariCP
3.3.1
org.springframework.boot
spring-boot-starter-jdbc
JdbcTemplate本身并不支持动态设置schema的功能,因此需要重新改造JdbcTemplate使其支持逻辑schema的动态设置。
在这里只展示部分代码,如果想查看全部代码可以下载查看。https://download.csdn.net/download/u013623958/11225293。
@Override
@Nullable
public T execute(StatementCallback action, String schema) throws DataAccessException {
Assert.notNull(action, "Callback object must not be null");
Connection con = DataSourceUtils.getConnection(obtainDataSource());
try {
con.setCatalog(schema);
} catch (SQLException e) {
e.printStackTrace();
}
try {
con.setCatalog(schema);
} catch (SQLException e) {
e.printStackTrace();
}
Statement stmt = null;
try {
stmt = con.createStatement();
applyStatementSettings(stmt);
T result = action.doInStatement(stmt);
handleWarnings(stmt);
return result;
}
catch (SQLException ex) {
// Release Connection early, to avoid potential connection pool deadlock
// in the case when the exception translator hasn't been initialized yet.
String sql = getSql(action);
JdbcUtils.closeStatement(stmt);
stmt = null;
DataSourceUtils.releaseConnection(con, getDataSource());
con = null;
throw translateException("StatementCallback", sql, ex);
}
finally {
JdbcUtils.closeStatement(stmt);
DataSourceUtils.releaseConnection(con, getDataSource());
}
}
接下来就可以根据自身业务动态设置schema了
List
通过Springboot将MyJdbcTemplate注入。
@Bean(name = "db1JdbcTemplate")
public MyJdbcTemplate Db1JdbcTemplate(@Qualifier("db1DataSource")DataSource dataSource) {
return new MyJdbcTemplate(dataSource);
}
@Primary
@Bean(name = "db1DataSourceProperties")
@Qualifier("db1DataSource")
@ConfigurationProperties(prefix = "spring.datasource.db1")
public DataSourceProperties db1DataSourceProperties() {
return new DataSourceProperties();
}
@Primary
@Bean(name = "db1DataSource")
@Qualifier("db1DataSource")
@ConfigurationProperties(prefix = "spring.datasource.db1")
public DataSource db1DataSource() {
return db1DataSourceProperties().initializeDataSourceBuilder().build();
}
同时SpringJDBC支持多数据源,这样一来业务基本满足。
https://download.csdn.net/download/u013623958/11225293。