使用Spring提供的工具类ScriptUtils执行sql脚本文件的一个注意事项
使用ScriptUtils.executeSqlScript方法执行脚本的时候需要手动释放数据库连接
注意,注意,注意
重要的事情说3遍,并且记录一下。截图中红框选中的部分: 这个方法不会释放数据库连接。我看网上不少人对这个工具类的使用,都没有注意这个问题。而且有些地方使用MyBatis,从MyBatis的SqlSession中获取数据库连接Connection,使用完之后没有释放。我想他们之所以没有发现这个问题是因为他们仅仅只是测试了一下,发现这个工具类这么用是"可以的",而且很方便,并没有在一个进程中进行多次测试。我也是因为使用quartz定时任务才发现的,定时任务每执行几天(一天执行一次)就会卡在某个地方不动了,起初我以为是因为sql脚本太复杂导致数据库一直在后台执行,今天我在看这个方法的说明时才发现了这么一段话。于是我就在Controller里面用这个工具类重复去执行一个简单sql文件,然后在页面不停发送请求,发现页面刷新固定次数(具体几次忘了)后获取数据库连接的代码:
Connection conn = dataSource.getConnection();
就会卡死。完整的Controller方法代码如下:
@GetMapping("/testScriptUtils")
public boolean testScriptUtils(){
try {
File newfile = new File("scripts/test.sql");
Resource resource = new FileSystemResource(newfile);
EncodedResource resourceDelegate = new EncodedResource(resource);
Connection conn = dataSource.getConnection();
ScriptUtils.executeSqlScript(conn, resource);
//DataSourceUtils.releaseConnection(conn, dataSource);
return true;
} catch (ScriptException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return false;
}
所以在使用这个工具类的时候,当它执行完了必须、必须、必须记得调用上述代码段中的被注释的方法:
DataSourceUtils.releaseConnection(conn, dataSource);
经测试,这样释放数据库连接之后就不会出现同样的问题了。此处主要针对使用了数据库连接池的情景,如果每次调用都创建新连接当然不会出现这个问题了,但是这样也是资源浪费,执行次数多了也会导致数据库连接资源不够用。在此记一下,大家可以借鉴