假定Java 程序中要定期执行 SQL 语句,因需求变更应修改原有 SQL 语句或者加上更多的语句时,不得不修改源代码,然后再次编译。要是把 SQL 语句写在单独的 SQL 脚本文件中,由 Java 程序来定时加载执行,那么每次改动时仅仅修改 SQL 脚本文件就行了。
Java 没有提供现成的东西,所以自己写了一个这样的 SQL 脚本执行类 SqlFileExecutor。支持通用的 SQL 脚本文件,"--" 作为注释前导符,分号 ";" 分隔语句。不支持 MySQL 的 /*...*/ 形式的注释格式。对于 Windows 和 Linux/Unix 下编辑的脚本文件都测试通过。这两个系统文件中的换行符不一样,Windows 是 "\r\n",Linux/Unix 是 "\n"。
50. /**
51. * 传入连接来执行 SQL 脚本文件,这样可与其外的数据库操作同处一个事物中
52. * @param conn 传入数据库连接
53. * @param sqlFile SQL 脚本文件
54. * @throws Exception
55. */
56. public void execute(Connection conn, String sqlFile) throws Exception {
57. Statement stmt = null;
58. List<String> sqlList = loadSql(sqlFile);
59. stmt = conn.createStatement();
60. for (String sql : sqlList) {
61. stmt.addBatch(sql);
62. }
63. int[] rows = stmt.executeBatch();
64. System.out.println("Row count:" + Arrays.toString(rows));
65. }
66.
67. /**
68. * 自建连接,独立事物中执行 SQL 文件
69. * @param sqlFile SQL 脚本文件
70. * @throws Exception
71. */
72. public void execute(String sqlFile) throws Exception {
73. Connection conn = DBCenter.getConnection();
74. Statement stmt = null;
75. List<String> sqlList = loadSql(sqlFile);
76. try {
77. conn.setAutoCommit(false);
78. stmt = conn.createStatement();
79. for (String sql : sqlList) {
80. stmt.addBatch(sql);
81. }
82. int[] rows = stmt.executeBatch();
83. System.out.println("Row count:" + Arrays.toString(rows));
84. DBCenter.commit(conn);
85. } catch (Exception ex) {
86. DBCenter.rollback(conn);
87. throw ex;
88. } finally {
89. DBCenter.close(null, stmt, conn);
90. }
91. }
92.
93. public static void main(String[] args) throws Exception {
94. List<String> sqlList = new SqlFileExecutor().loadSql(args[0]);
95. System.out.println("size:" + sqlList.size());
96. for (String sql : sqlList) {
97. System.out.println(sql);
98. }
99. }
100.}