天天看点

finally被置空导致数据库连接挂死

        今天写了几行代码,向数据库插入一篇文章,程序执行表现很好,完全按照我的意愿去走,可以写入时都成功写入数据库,该失败时果断失败。可是当我回头再看代码时,突然惊恐万分。这里面隐藏了多么弱智的bug,甚至说是外行的错误,可是想了一下,似乎又很有可能出现,一不小心就有可能再次写出来,所以写个博警告下自己。

        向数据库插入文章的代码,这里面至少隐藏了三个超级弱智的致命错误:

public int insertThreadBeanIntoDB(ThreadBean threadbean){

ErrorTypeBean ErrorType  = ErrorTypeBean.getErrorTypeHandle();

if(null == threadbean){

return ErrorType.getErrorCodeByErrorType("NULL_POINTER");

}

Connection conn   = null;

PreparedStatement  ps       = null;

int               result = 0;

try{

conn = new ConnDB().getConnection();
ps = conn.prepareStatement("insert into thread values(?,?,?,?,?,?,?)");
ps.setString(1, threadbean.getThread_id().toString());
ps.setString(2, threadbean.getTread_title());
ps.setString(3, threadbean.getTread_content());
ps.setString(4, threadbean.getThread_create_time().toString());
ps.setString(5, threadbean.getThread_update_time().toString());
ps.setString(6, threadbean.getThread_hit_number().toString());
ps.setString(7, threadbean.getThread_user().toString());
result=ps.executeUpdate();
if(0 == result){
return  ErrorType.getErrorCodeByErrorType("DB_OPERATION_ERROE");
}
}catch(Exception e){
e.printStackTrace();
return ErrorType.getErrorCodeByErrorType("UNKNOWN_ERROR");
}finally{
this.closeConn();

}

return ErrorType.getErrorCodeByErrorType("NO_ERROR");

}

在try里面成功操作数据库后,直接将结果返回;

catch到异常后直接返回错误码;

在程序的最后直接返回成功。

严重没睡醒!

        无论是在在try里面还是在catch里面返回,都会讲finally挂起,导致数据库连接无法关闭。在上面的写法下,如果出现错误,catch会拦截下来,所以出现错误的时候不会有任何不正常的表现,但是finally被置空了;而如果执行成功,则catch无效,可以在最后返回成功,程序也不会出现表面的失败。而一旦try里面的返回条件满足,则try就会将finally置空,撇开上面的try里面的情况,如果稍微处理复杂点,可能会出现,在操作成功的时候也会全部将finally置空,这时,finally将永远得不到执行,所有数据库连接将全部不能关闭。

        这种错误在运行的时候不会出现任何异常表现,一旦时过境迁,这种错误将无从查起,而系统频繁出现数据库自然耗尽,解决办法只有重启...重启...再重启。当然了,也可以通过查看数据库连接的使用情况来分析问题的所在。但是问题已经升级不止一个档次了,小疏忽引发的大问题,不可疏忽。

        正确写法:

public int insertThreadBeanIntoDB(ThreadBean threadbean){

ErrorTypeBean ErrorType                         = ErrorTypeBean.getErrorTypeHandle();

int                        operation_code              = ErrorType.getErrorCodeByErrorType("NO_ERROR");

if(null == threadbean){

return ErrorType.getErrorCodeByErrorType("NULL_POINTER");

}

Connection  conn   = null;

PreparedStatement  ps       = null;

int               result = 0;

try{

conn = new ConnDB().getConnection();
ps = conn.prepareStatement("insert into thread values(?,?,?,?,?,?,?)");
ps.setString(1, threadbean.getThread_id().toString());
ps.setString(2, threadbean.getTread_title());
ps.setString(3, threadbean.getTread_content());
ps.setString(4, threadbean.getThread_create_time().toString());
ps.setString(5, threadbean.getThread_update_time().toString());
ps.setString(6, threadbean.getThread_hit_number().toString());
ps.setString(7, threadbean.getThread_user().toString());
result=ps.executeUpdate();
if(0 == result){
operation_code  = ErrorType.getErrorCodeByErrorType("DB_OPERATION_ERROE");
}
}catch(Exception e){
e.printStackTrace();
operation_code  = ErrorType.getErrorCodeByErrorType("UNKNOWN_ERROR");
}finally{
this.closeConn();

}

return operation_code;

}

如果非得在try-catch里面返回,name至少应该写在finally里面,写在关闭数据库连接之后。