好的做法:JDBC连接

可能重复:
何时在JDBC中关闭Connection,Statement,PreparedStatement和ResultSet

我已经为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和它们的ResultSet也都关闭了,对吧?

用法:

 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之前,必须关闭它。 我遇到了严重问题,因为我没有关闭PreparedStatements。 事实certificate,在数据库服务器上,分配的资源仅在显式调用PreparedStatement.close()后才被释放。

正如bdares所评论的那样,Connection应尽可能不经常打开和关闭。

连接池

使用连接池。 应用程序中的每个事务都将从此池获得连接,执行所需的所有操作,回滚或提交并关闭连接(它将conn返回到池中)。

您可以为Query对象提供对池的引用,open将获得连接,close将关闭它(实际上将其返回)。

准备好的声明

尝试将已准备好的语句重用于类似查询。 这样,数据库将重用以前的查询计划,并且速度会更快。 如果您正在执行相同表单的大量查询,那么这很有意义。

怎么样?

  • 保持最后PS开放
  • 如果您关闭连接或其他什么,请关闭它
  • 如果您查询与之前相同的查询字符串,则重复使用您保存的PS
  • 如果它不是相同的查询字符串…关闭它并创建一个新的

最佳实践是:对所有查询使用单个Connection对象,如果这些队列是同一方法的一部分,并且每个查询在使用后关闭PreparedStatement。

使用连接池。 所以你不要继续创作。