网站首页 > 博客文章 正文
ScriptRunner工具类在前面的章节中我们已经使用过几次了,该工具类用于读取脚本文件中的SQL语句并执行,使用起来比较简单。下面是一个使用ScriptRunner执行SQL脚本的案例,代码如下:
public void initData() throws Exception {
// 初始化数据
Class.forName("org.hsqldb.jdbcDriver");
// 获取Connection对象
Connection conn = DriverManager.getConnection("jdbc:hsqldb:mem:mybatis",
"sa", "");
// 使用Mybatis的ScriptRunner工具类执行数据库脚本
ScriptRunner scriptRunner = new ScriptRunner(conn);
// 不输出sql日志
scriptRunner.setLogWriter(null);
scriptRunner.runScript(Resources.getResourceAsReader("create-table.sql"));
System.out.println("------------------------");
}
如上面的代码所示,ScriptRunner工具类的构造方法需要一个java.sql.Connection对象作为参数。创建ScriptRunner对象后,调用该对象的runScript()方法即可,该方法接收一个读取SQL脚本文件的Reader对象作为参数。
接下来我们主要分析runScript方法
public void runScript(Reader reader) {
// 设置事务是否自动提交
setAutoCommit();
try {
// 是否一次性批量执行脚本文件中的所有SQL语句
if (sendFullScript) {
// 调用executeFullScript()方法一次性执行脚本文件中的所有SQL语句
executeFullScript(reader);
} else {
// 调用executeLineByLine()方法逐条执行脚本中的SQL语句
executeLineByLine(reader);
}
} finally {
rollbackConnection();
}
}
如上面的代码所示,ScriptRunner类的runScript()方法的逻辑比较清晰,具体做了以下几件事情:
(1)调用setAutoCommit()方法,根据autoCommit属性的值设置事务是否自动提交。
(2)判断sendFullScript属性值,如果值为true,则调用executeFullScript()方法一次性读取SQL脚本文件中的所有内容,然后调用JDBC中Statement对象的execute()方法一次性执行脚本中的所有SQL语句。
(3)如果sendFullScript属性值为false,则调用executeLineByLine()方法逐行读取SQL脚本文件,以分号作为一条SQL语句结束的标志,逐条执行SQL语句。
接下来我们重点了解一下executeLineByLine()方法的实现,代码如下:
private void executeLineByLine(Reader reader) {
StringBuilder command = new StringBuilder();
try {
BufferedReader lineReader = new BufferedReader(reader);
String line;
// 按照行计算
while ((line = lineReader.readLine()) != null) {
handleLine(command, line);
}
commitConnection();
checkForMissingLineTerminator(command);
} catch (Exception e) {
String message = "Error executing: " + command + ". Cause: " + e;
printlnError(message);
throw new RuntimeSqlException(message, e);
}
}
如上面的代码所示,该方法中对脚本中的内容逐行读取,然后调用handleLine()方法处理每行读取的内容。handleLine()方法内容如下:
private void handleLine(StringBuilder command, String line) throws SQLException {
String trimmedLine = line.trim();
if (lineIsComment(trimmedLine)) {
Matcher matcher = DELIMITER_PATTERN.matcher(trimmedLine);
if (matcher.find()) {
delimiter = matcher.group(5);
}
println(trimmedLine);
} else if (commandReadyToExecute(trimmedLine)) {
command.append(line.substring(0, line.lastIndexOf(delimiter)));
command.append(LINE_SEPARATOR);
println(command);
executeStatement(command.toString());
command.setLength(0);
} else if (trimmedLine.length() > 0) {
command.append(line);
command.append(LINE_SEPARATOR);
}
}
如上面的代码所示,handleLine()方法的逻辑如下:
(1)调用lineIsComment()方法判断本行内容是否为注释,如果为注释内容,则打印注释内容。
(2)调用commandReadyToExecute()方法判断本行中是否包含分号。
(3)如果本行包含分号,则说明该行是一条完整SQL的结尾。需要截取分号之前的SQL内容,与前面读取到的不包含分号的行一起组成一条完整的SQL语句执行。
(4)若该行中不包含分号,则说明该条SQL语句未结束,追加本行内容到之前读取的内容中,继续读取下一行。
猜你喜欢
- 2024-10-04 基础架构之Gitlab Runner(gitlab runner helm)
- 2024-10-04 gitlab runner 部署案例(gitlab gitlab-runner)
- 2024-10-04 GitLab 12.1版本发布,支持Pages自动https证书、机密MR请求等
- 2024-10-04 Gitlab Runner的分布式缓存实战(gitlab ci 缓存)
- 2024-10-04 性能测试脚本的编写和调试(性能测试脚本怎么写)
- 2024-10-04 在DEEPIN上,配置ATOM+BUILD的通用即时编译器
- 2024-10-04 携程机票App KMM iOS工程配置实践
- 2024-10-04 GitLabCI作业中如何使用私有仓库镜像?
- 2024-10-04 BAIR最新RL算法超越谷歌Dreamer,性能提升2.8倍
- 2024-10-04 Gitlab持续集成与发布在PHP中的应用
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- ifneq (61)
- 字符串长度在线 (61)
- googlecloud (64)
- messagesource (56)
- promise.race (63)
- 2019cad序列号和密钥激活码 (62)
- window.performance (66)
- qt删除文件夹 (72)
- mysqlcaching_sha2_password (64)
- ubuntu升级gcc (58)
- nacos启动失败 (64)
- ssh-add (70)
- jwt漏洞 (58)
- macos14下载 (58)
- yarnnode (62)
- abstractqueuedsynchronizer (64)
- source~/.bashrc没有那个文件或目录 (65)
- springboot整合activiti工作流 (70)
- jmeter插件下载 (61)
- 抓包分析 (60)
- idea创建mavenweb项目 (65)
- vue回到顶部 (57)
- qcombobox样式表 (68)
- tomcatundertow (58)
- pastemac (61)
本文暂时没有评论,来添加一个吧(●'◡'●)