之前接手一个已完成的批量项目,发现其代码写的一塌糊涂,真是醉了,使用了JDBC技术,虽然JDBC比较老旧了,现在也不常用,但是还是记录一下。
跑了一下程序,报错、、、看了一眼控制台日志,常见的JDBC连接池满了,原因一定是使用了链接但不释放导致的。常见的解决办法有两种,第一,扩大链接池数量,治标不治本;第二,检查程序,使用完的链接要关闭。当即快速检查了程序,发现多处调用JDBC开启链接,但最后都没关闭,并且由于批量程序数据量大,有部分循环调用的情况,导致直接超出连接数量。于是在所有调用完之后都加了close代码。
再次测试程序,链接数不报错,但是报了超出打开游标的最大数。分析原因,由于部分方法调用JDBC,取到结果集,在结果集内再次循环调用JDBC链接,数据量过多导致;但是如果将游标和结果集resultset关闭,那代码内的循环也将不可使用。时间紧也来不及重构别人的代码,读懂都得耗费时间,于是决定写公共工具类来快速解决。
写代码思路,第一,工具类单独调取JDBC,原代码只调工具类,工具类使用一次就立即关闭链接、游标和结果集;但是查询类型的需要使用结果集,不可关闭,所以第二查询类型单独写方法并在结束时调用close。代码如下:
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class SQLHelper {
private Connection con = null;
private Statement stmt = null;
private PreparedStatement pst = null;
private ResultSet rs = null;
/**
* 执行 SQL 语句,返回结果为结果集
* 主要用于执行查询语句
* @param sql SQL 语句
* @param cmdParams SQL的参数
*/
public ResultSet queryHelper(String sql,Object... cmdParams){
con=JDBCUtil.getDBConnect();
try {
pst = con.prepareStatement(sql);
int i = 1;
for (Object item : cmdParams)
{
pst.setObject(i, item);
i++;
}
rs = pst.executeQuery();
return rs;
} catch (SQLException e) {
e.printStackTrace();
try {
con.rollback();
con.setAutoCommit(true);
} catch (SQLException e1) {
e1.printStackTrace();
}
return null;
}
}
public void closeAll(){
JDBCUtil.clearResource(con,stmt,pst,rs);
}
/**
* 执行 SQL 语句,返回结果为整型
* 主要用于执行非查询语句
* @param sql SQL 语句
* @return 非负数:正常执行; -1:执行错误; -2:连接错误
*/
public int updateHelper(String sql,Object... cmdParams){
con=JDBCUtil.getDBConnect();
try {
pst = con.prepareStatement(sql);
int i = 1;
for (Object item : cmdParams)
{
pst.setObject(i, item);
i++;
}
int k;
k = pst.executeUpdate();
con.commit();
return k;
} catch (SQLException e) {
e.printStackTrace();
try {
con.rollback();
con.setAutoCommit(true);
} catch (SQLException e1) {
e1.printStackTrace();
}
return 0;
}finally{
JDBCUtil.clearResource(con,stmt,pst,rs);
}
}
}
具体说明注释里也写的很清楚,就不多说。看下代码调用:
SQLHelper sqh = new SQLHelper();
String sql = "select XXX from XXXXXXXXXXX where XXXXXXXXXXXXXXXXXXXX>0";
ResultSet rst = sqh.queryHelper(sql);
这种查询类型的,拿到结果集使用完毕后,调用上面工具类中closeAll()方法即刻。
时间紧,就随便写这些,之后再进行总结和扩展吧。