良好做法:JDBC连接
问题内容:
我已经为JDBC连接编写了一个简单的包装程序,它可以工作,但是我想通过最佳实践来对其进行改进。它基本上有类似的方法open()
,close()
,isOpened()
,select()
,insert()
,update()
,delete()
和batch()
。为简单起见,我仅在此处发布前4种方法。
public class Query{
private Connection con;
private PreparedStatement ps;
private ResultSet rs;
//Database.open() returns a Connection ready to use
public void open (Database database) throws DatabaseException, SQLException{
if (!isOpened ()){
con = database.open ();
}
}
public void close () throws SQLException{
if (isOpened ()){
if (ps != null) ps.close ();
con.close ();
con = null;
}
}
public boolean isOpened (){
return con != null;
}
//The query string is the query without the word "select" and can use placeholders (?)
//The args param it's just an array owith the values of this placeholders
public ResultSet select (String query, Object[] args) throws SQLException{
if (ps != null) ps.close ();
if (isOpened ()){
ps = con.prepareStatement ("select " + query);
if (args != null){
for (int i=0; i<args.length; i++){
ps.setObject (i+1, args[i]);
}
}
rs = ps.executeQuery ();
}
return rs;
}
}
笔记:
- 可以重复使用同一查询对象,例如打开和关闭它,以及在再次打开之后。
- 我不是关闭每个查询的连接,而是关闭准备好的语句(这是正确的,或者我可以让准备好的语句保持打开状态,因为Connection对象会关闭它吗?)
- 当我关闭时
Connection
,所有PreparedStatement
s和它们的ResultSet
s也都关闭了,对吗?
用法:
Database database;
//Database initialization
Query query = new Query ();
query.open (database);
ResultSet rs = query.select ("* from user where name=?", new String[]{ "MyName" });
doSomethingWithResult1 (rs);
//Connection is not closed here
ResultSet rs = query.select ("coordx from point where coordy=? and coordz=?", new Float[]{ 0.1, 0.2 });
doSomethingWithResult2 (rs);
query.close ();
query.open (database);
ResultSet rs = query.select ("* from user where name=?", new String[]{ "MyName" });
doSomethingWithResult1 (rs);
//Connection is not closed here
ResultSet rs = query.select ("coordx from point where coordy=? and coordz=?", new Float[]{ 0.1, 0.2 });
doSomethingWithResult2 (rs);
query.close ();
你怎么看?每次查询后都应该关闭并打开连接吗?在同一连接上进行每个查询后,是否可以打开PreparedStatement?这是一个好的设计?
问题答案:
使用完PreparedStatement之后,必须在同一连接上创建新的PreparedStatement之后,再关闭它。我遇到了严重的问题,因为我没有关闭PreparedStatements。事实证明,在数据库服务器上,只有在显式调用PreparedStatement.close()之后才释放已分配的资源。
如bdares所评论,应尽可能不频繁地打开和关闭Connection。