正确及时关闭数据库连接

1.1  概述

JAVAEE后台编码时,时常出现没有正确及时关闭数据库连接资源(ConnectionStatement, ResultSet)现象,导致程序运行过程中出现意想不到的错误。

本文档首先介绍正确使用数据库资源的方式,以此演示代码中经常出现的问题及误解。

 

2.     数据库资源接口

l         Connection

l         Statement

l         ResultSet

 

2.1  通用的使用方式

1)       获取Connection

2)       创建Statement

3)       获取ResultSet

 

 

 

  
 

正确及时关闭数据库连接

 

1.1  概述

JAVAEE后台编码时,时常出现没有正确及时关闭数据库连接资源(ConnectionStatement, ResultSet)现象,导致程序运行过程中出现意想不到的错误。

本文档首先介绍正确使用数据库资源的方式,以此演示代码中经常出现的问题及误解。

 

2.     数据库资源接口

l         Connection

l         Statement

l         ResultSet

 

2.1  通用的使用方式

1)       获取Connection

2)       创建Statement

3)       获取ResultSet

//获取Connection

Connection conn = ;

try {

//创建Statement

Statement stm = conn.createStatement();

try {

//获取数据集

ResultSet rs = stm.executeQuery("select * from ....");

try {

    //读取数据集

} finally {

    //关闭ResultSet

rs.close();

}

} finally {

    //关闭Statement

stm.close();

}

} finally {

    //关闭Connection

conn.close();

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

3.     读写数据库时常见的问题

3.1  认为不需要关闭数据库资源

错误的代码示例:

final ResultSet rs = DBAdapter.executeQuery(unitCode, SQL_GET_USERNAME);

// 对数据集的处理

if( rs.next()){

}

  

 

 

 

 

 


 

有以下原因造成没有关闭数据库连接资源:

l         不清楚数据库连接是否关闭。
这在新手中普便存在这种问题。

 

l         误认为容器(EJB容器或数据总线)会自动关闭。
不能过份依赖容器,因为容器关闭数据库资源的功能是有限的,且不可靠的。

 

3.2  没有使用正确的方法,导致没有真正关闭数据库资源

错误的代码示例:

注:DBAdapter类封装了读取和关闭数据库资源的功能

final ResultSet rs = DBAdapter.executeQuery(unitCode, SQL_GET_USERNAME);

try {

    // 对数据集的处理

} finally {

rs.close();

}

  

 

 

 

 

 

 

 


 

final ResultSet rs = DBAdapter.executeQuery(unitCode, SQL_GET_USERNAME);

try {

    // 对数据集的处理

} finally {

    DBAdapter.freeDBResource(rs);

}

存在的问题是 StatementConnection没有关闭,正确的调用方式应是:

 

 

 

 

 

 

 

 

3.3  因失误没有关闭ResultSet

这种错误主要是由于调用其他方法时,需要传递ResultSet作为参数,习惯性的创建ResultSet没有关闭。

错误的代码示例:

PreparedStatement stm = DBAdapter.prepareStatement(unitCode, sql);

try {

String rs = DBAdapter.resultSetToXml(stm.executeQuery());

return rs;

} finally {

DBAdapter.freeDBResource(stm);

}

  

 

 

 

 

 

 

 

 

 


 

正确的代码如下:

PreparedStatement stm = null;

ResultSet rs = null;

try {

    stm = DBAdapter.prepareStatement(unitCode, sql);

    rs = stm.executeQuery();

    String ret = DBAdapter.resultSetToXml(rs);

    return ret;

} finally {

    if (rs != null) {

        DBAdapter.freeDBResource(rs);

    } else if (stm != null) {

        DBAdapter.freeDBResource(stm);

    }

}

  

 

 

 

 

 

 

 

 

 

 

 

 

 

 


 

3.4  程序出现异常时没有关闭数据库连接

错误代码示例:

final ResultSet rs = DBAdapter.executeQuery(unitCode, SQL_GET_USERNAME);

// 对数据集的处理

DBAdapter.freeDBResource(rs);

  

 

 

 

 

 

 

 


 

正确的代码如下:

final ResultSet rs = DBAdapter.executeQuery(unitCode, SQL_GET_USERNAME);

try {

// 对数据集的处理

} finally {

    DBAdapter.freeDBResource(rs);

}

  

 

 

 

 

 

 

 

 

 


 

3.5  在关闭ResultSet前被重新创建

错误代码示例:

 

ResultSet rs = DBAdapter.executeQuery(unitCode, SQL_GET_USERNAME);

try {

// 对数据集的处理

rs = DBAdapter.executeQuery(unitCode, SQL_GET_DISPLAYNAME);

} finally {

    DBAdapter.freeDBResource(rs);

}

  

 

 

 

 

 

 

 

 

 

 


 

正确的代码如下:

final ResultSet rs = DBAdapter.executeQuery(unitCode, SQL_GET_USERNAME);

try {

// 对数据集的处理

ResultSet rsDisplay = DBAdapter.executeQuery(unitCode, SQL_GET_DISPLAYNAME);

try {

    ……

} finally {

DBAdapter.freeDBResource(rsDisplay);

}

} finally {

    DBAdapter.freeDBResource(rs);

}

  

 

 

 

 

 

 

 

 

 

 

 

 

 


 

注:把ResultSet变量声明为常量(final),可有效防止此类问题的产生。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


3.     读写数据库时常见的问题

3.1  认为不需要关闭数据库资源

错误的代码示例:

final ResultSet rs = DBAdapter.executeQuery(unitCode, SQL_GET_USERNAME);

// 对数据集的处理

if( rs.next()){

}

 

 

 

 

 


有以下原因造成没有关闭数据库连接资源:

l         不清楚数据库连接是否关闭。
这在新手中普便存在这种问题。

l         误认为容器(EJB容器或数据总线)会自动关闭。
不能过份依赖容器,因为容器关闭数据库资源的功能是有限的,且不可靠的。

 

3.2  没有使用正确的方法,导致没有真正关闭数据库资源

错误的代码示例:

注:DBAdapter类封装了读取和关闭数据库资源的功能

final ResultSet rs = DBAdapter.executeQuery(unitCode, SQL_GET_USERNAME);

try {

    // 对数据集的处理

} finally {

rs.close();

}

 

 

 

 

 

 

 


final ResultSet rs = DBAdapter.executeQuery(unitCode, SQL_GET_USERNAME);

try {

    // 对数据集的处理

} finally {

    DBAdapter.freeDBResource(rs);

}

存在的问题是StatementConnection没有关闭,正确的调用方式应是:

 

 

 

 

 

 

 

3.3  因失误没有关闭ResultSet

这种错误主要是由于调用其他方法时,需要传递ResultSet作为参数,习惯性的创建ResultSet没有关闭。

错误的代码示例:

PreparedStatement stm = DBAdapter.prepareStatement(unitCode, sql);

try {

String rs = DBAdapter.resultSetToXml(stm.executeQuery());

return rs;

} finally {

DBAdapter.freeDBResource(stm);

}

 

 

 

 

 

 

 

 

 


正确的代码如下:

PreparedStatement stm = null;

ResultSet rs = null;

try {

    stm = DBAdapter.prepareStatement(unitCode, sql);

    rs = stm.executeQuery();

    String ret = DBAdapter.resultSetToXml(rs);

    return ret;

} finally {

    if (rs != null) {

        DBAdapter.freeDBResource(rs);

    } else if (stm != null) {

        DBAdapter.freeDBResource(stm);

    }

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 


3.4  程序出现异常时没有关闭数据库连接

错误代码示例:

final ResultSet rs = DBAdapter.executeQuery(unitCode, SQL_GET_USERNAME);

// 对数据集的处理

DBAdapter.freeDBResource(rs);

 

 

 

 

 

 

 


正确的代码如下:

final ResultSet rs = DBAdapter.executeQuery(unitCode, SQL_GET_USERNAME);

try {

// 对数据集的处理

} finally {

    DBAdapter.freeDBResource(rs);

}

 

 

 

 

 

 

 

 

 


3.5  在关闭ResultSet前被重新创建

错误代码示例:

 

ResultSet rs = DBAdapter.executeQuery(unitCode, SQL_GET_USERNAME);

try {

// 对数据集的处理

rs = DBAdapter.executeQuery(unitCode, SQL_GET_DISPLAYNAME);

} finally {

    DBAdapter.freeDBResource(rs);

}

 

 

 

 

 

 

 

 

 

 


正确的代码如下:

final ResultSet rs = DBAdapter.executeQuery(unitCode, SQL_GET_USERNAME);

try {

// 对数据集的处理

ResultSet rsDisplay = DBAdapter.executeQuery(unitCode, SQL_GET_DISPLAYNAME);

try {

    ……

} finally {

DBAdapter.freeDBResource(rsDisplay);

}

} finally { 

   DBAdapter.freeDBResource(rs);

}

 

 

 

 

 

 

 

 

 

 

 

 

 


注:把ResultSet变量声明为常量(final),可有效防止此类问题的产生。

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值