MyBatis 3源码深度解析
上QQ阅读APP看书,第一时间看更新

3.2 使用ScriptRunner执行脚本

ScriptRunner工具类在前面的章节中我们已经使用过几次了,该工具类用于读取脚本文件中的SQL语句并执行,使用起来比较简单。下面是一个使用ScriptRunner执行SQL脚本的案例,代码如下:

如上面的代码所示,ScriptRunner工具类的构造方法需要一个java.sql.Connection对象作为参数。创建ScriptRunner对象后,调用该对象的runScript()方法即可,该方法接收一个读取SQL脚本文件的Reader对象作为参数。完整案例读者可以参考随书源码mybatis-chapter03项目的com.blog4java.mybatis.ScriptRunnerExample类。

ScriptRunner工具类中提供了一些属性,用于控制执行SQL脚本的一些行为,代码如下:

我们可以直接调用这些属性对应的Setter方法来控制ScriptRunner工具类执行SQL脚本的行为。ScriptRunner类中仅提供了一个runScript()方法用于执行SQL脚本文件。接下来我们简单地分析一下该方法的实现源码:

如上面的代码所示,ScriptRunner类的runScript()方法的逻辑比较清晰,具体做了以下几件事情:

(1)调用setAutoCommit()方法,根据autoCommit属性的值设置事务是否自动提交。

(2)判断sendFullScript属性值,如果值为true,则调用executeFullScript()方法一次性读取SQL脚本文件中的所有内容,然后调用JDBC中Statement对象的execute()方法一次性执行脚本中的所有SQL语句。

(3)如果sendFullScript属性值为false,则调用executeLineByLine()方法逐行读取SQL脚本文件,以分号作为一条SQL语句结束的标志,逐条执行SQL语句。

接下来我们重点了解一下executeLineByLine()方法的实现,代码如下:

如上面的代码所示,该方法中对脚本中的内容逐行读取,然后调用handleLine()方法处理每行读取的内容。handleLine()方法内容如下:

如上面的代码所示,handleLine()方法的逻辑如下:

(1)调用lineIsComment()方法判断本行内容是否为注释,如果为注释内容,则打印注释内容。

(2)调用commandReadyToExecute()方法判断本行中是否包含分号。

(3)如果本行包含分号,则说明该行是一条完整SQL的结尾。需要截取分号之前的SQL内容,与前面读取到的不包含分号的行一起组成一条完整的SQL语句执行。

(4)若该行中不包含分号,则说明该条SQL语句未结束,追加本行内容到之前读取的内容中,继续读取下一行。