网站首页 > 博客文章 正文
思考:如果让你去实现 运行脚本文件中的SQL 功能,你会怎样实现呢?
简介
ScriptRunner工具类用于读取脚本文件中的SQL语句并执行。
开发环境
- JDK1.8
- MyBatis3.5.7
- MySQL8
简单示例
Maven 依赖
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.7</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.29</version>
</dependency>
废话不多说,下面是一个使用ScriptRunner执行SQL脚本的简单示例,代码如下:
try {
// 数据库连接
Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1/mybatis?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC", "root", "abc123");
// 创建ScriptRunner对象
ScriptRunner scriptRunner = new ScriptRunner(connection);
// 读取classpath路径下的文件,返回Reader对象
Reader reader = Resources.getResourceAsReader("schema.sql");
// 执行SQL脚本
scriptRunner.runScript(reader);
} catch (Exception e) {
e.printStackTrace();
}
简单细说一下,使用ScriptRunner执行SQL脚本的操作步骤:
(1)创建数据库连接,创建ScriptRunner对象时要用;
(2)调用构造方法创建ScriptRunner对象,此构造方法需要一个java.sql.Connection对象作为参数,在(1)中我们已经创建;
(3)读取 classpath 路径下的脚本文件内容,返回Reader对象;
(4)调用ScriptRunner对象的runScript()方法执行脚本,参数为(3)中创建的Reader对象。
runScript()方法源码:
public void runScript(Reader reader) {
// 设置事务是否自动提交
setAutoCommit();
try {
// 是否一次性批量执行文件中的所有SQL语句
if (sendFullScript) {
// 一次性批量执行文件中的所有SQL语句
executeFullScript(reader);
} else {
// 逐条执行文件中的所有SQL语句
executeLineByLine(reader);
}
} finally {
rollbackConnection();
}
}
runScript()方法调用setAutoCommit(),根据autoCommit属性的值设置事务是否自动提交,然后判断sendFullScript属性的值。如果sendFullScript值为 true,则一次性批量执行脚本文件中的所有 SQL 语句;如果sendFullScript值为 false,则逐条执行脚本文件中的 SQL 语句。
sendFullScript属性的值默认为 false,这里是逐条执行脚本文件中的 SQL 语句。
executeLineByLine()方法源码:
private void executeLineByLine(Reader reader) {
// 要执行的SQL语句
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);
}
}
executeLineByLine()方法逐行读取脚本文件的内容,然后调用handleLine()方法处理每行内容。
handleLine()方法源码:
private void handleLine(StringBuilder command, String line) throws SQLException {
String trimmedLine = line.trim();
if (lineIsComment(trimmedLine)) { // 判断该行是否是SQL注释
Matcher matcher = DELIMITER_PATTERN.matcher(trimmedLine);
if (matcher.find()) {
delimiter = matcher.group(5);
}
println(trimmedLine);
} else if (commandReadyToExecute(trimmedLine)) { // 判断该行是否包含分号
// 获取该行分号之前的内容,追加到当前SQL语句
command.append(line, 0, line.lastIndexOf(delimiter));
// 追加行分隔符
command.append(LINE_SEPARATOR);
// 打印当前SQL语句
println(command);
// 执行当前SQL语句
executeStatement(command.toString());
// 清空SQL语句
command.setLength(0);
} else if (trimmedLine.length() > 0) { // 该行不包含分号,即当前SQL语句未结束
// 追加当前行内容
command.append(line);
// 追加行分隔符
command.append(LINE_SEPARATOR);
}
}
handleLine()方法的逻辑:
参考
《MyBatis3源码深度解析》,江荣波
猜你喜欢
- 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)
本文暂时没有评论,来添加一个吧(●'◡'●)