最近要研究多Saas多租户做一个教务管理系统,数据隔离方式有很多种,有表隔离,字段隔离,库隔离,但是后面最终选择用库隔离去做,以每个学校都有一个单独的库。但是用库隔离的话就需要在添加新租户的时候我们需要初始化租户相关的数据库,看了网上很多的执行sql脚本的例子有用原始的jdbc获取一个连接然后用io去自己读文件去执行sql文件太麻烦了,最后选择了用ScriptRunner来执行,具体看代码。
1.这里注入SqlSessionFactory下面要用他后去执行连接
@Resource
private SqlSessionFactory sqlSessionFactory;
2.这里是用ScriptRunner执行sql脚本的具体步骤,切换数据源根据自己配置的多数据源进行去切换。我这里应为sql脚本执行比较久,所以我用线程池去执行,没有线程池的小伙伴可一把 @Async("taskExecutor")去掉,或者 new Thread的方式去实现都可以,反正万变不离其中
@Async("taskExecutor")
public void initTenantSql(TenantInfoParam tenantInfoParam){
//切换租户对应的数据源
CurrentDataSourceContext.setDataSourceType(tenantInfoParam.getDbCode());
//可以通过上面的注入方式获取,可以通过工具获取
//sqlSessionFactory = SpringUtil.getBean(SqlSessionFactory.class);
Connection connection = sqlSessionFactory.openSession().getConnection();
ScriptRunner runner = new ScriptRunner(connection);
//设置字符集,不然中文乱码插入错误
Resources.setCharset(Charset.forName("UTF-8"));
//设置是否输出日志
runner.setLogWriter(new PrintWriter(System.out));
//遇到错误停止
runner.setStopOnError(true);
//设置取消自动提交
runner.setAutoCommit(false);
// 绝对路径读取
// Reader read = new FileReader(new File("f:\\test.sql"));
// 从class目录下直接读取
Reader read = null;
try {
//tenant_init.sql 放在resource下的template中
read = Resources.getResourceAsReader( "template/tenant_init.sql");
} catch (IOException e) {
e.printStackTrace();
}
runner.runScript(read);
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
注:设置输出日志那里在生产中可以把他置空,开发中可以让他打印在控制台。ScriptRunner不止可以sql脚本文件,也可以txt文件只要里面是正常的sql语句就行,他可以之自定义语句分割符号。喜欢研究的小伙伴可以去研究下,但一般执行txt文本的情况一般很少,其实他内部也是通过流去实现的。
第一次写文章,如有不妥之处请各位大佬指正共同学习
参考文章:使用MyBatis中的ScriptRunner来执行sql文件脚本,实现启动自动部署数据库_一枚JAVA萌新的进阶之旅-CSDN博客_scriptrunner执行存储过程