一、连接池简介
与数据库建立连接是最耗时的操作之一,而且数据库都有最大连接数的限制。假设数据库为每个用户都建议一个连接,很明显是不切实际的。Tomcat服务器可以事先准备数个、几十个预备连接对象,存放在称作连接池的容器当中,当用户需要与数据库打交道时,只需要从连接池中取出一个连接对象即可,用完之后得把连接对象返还给连接池。连接池中已经没有对象,而用户又想与数据库打交道,那么只有等待,直到连接池有了连接对象。
二、连接对象悄然耗尽?
随便拿起一本Java Web入门书籍,肯定都会有不同层度的介绍JDBC的基础知识。绝大部分书籍都会记载先加载某某驱动程序,其次和指定数据库建立连接,然后执行SQL语句,接着可能返与不返回结果集,最后关闭连接等等。没有任何问题,但是应用相同的章法,也就是使用连接池技术后,很多初学者将会遇到尴尬的问题,为何我的程序访问了几次以后,服务器就罢工了?最后不得已重启Tomcat,你可能会认为提高最大连接数,能在一定程度上缓解问题,但这可能只是治标的办法之一。连接对象是相当重要,连接对象耗尽更可怕,是谁扼杀了宝贵的连接对象?
三、罪魁祸首是Java代码
我们先来看一组极具代表性的try-catch语句:
- try
- {
- }
- catch(Exception e)
- {
- }
- finally
- {
- db.close();
- }
这是Java与数据库打交道时必不可少的、死板的异常类语句,我们都会在try{}里头写有关核心语句,譬如实例化一个ResultSet对象即将对单条SQL语句进行查询,或者对某一数据表进行update,最终调用close()方法关闭连接对象。这是没有问题的,连接对象会乖乖的回到连接池当中。如果你打算同时对多条SQL语句进行操作时,可要小心了,我们先看一下一组try-catch语句:
- try
- {
- rs = db.executeQuery(String sql);
- while (rs.next())
- {
- }
- rs = db.executeQuery(String sql2);
- while (rs.next())
- {
- }
- }
- catch (SQLException e)
- {
- }
- finally
- {
- db.close();
- }
如果你如此写,感觉还是没有问题的话,那应该兴庆你的课程设计甚至毕业设计没有使用连接池技术。这里还是将要引用我开篇的连接池简介中这么一句:当用户需要与数据库打交道时,只需要从连接池中取出一个连接对象即可,用完之后得把连接对象返还给连接池。我打算跟好友借钱,上午借1块,下午借5块,我第二天可以还他6块钱,没有问题,但是你不还,问题就相当比较大了。按理说,最终的db.close()应该能够同时关闭两个rs对象,实际上却无法实现这样的操作,这也是为什么连接对象会悄然耗尽的缘由,还是那么一句,用完就放回。把上一组代码稍微修改,就能解决连接对象耗尽的问题。
- try
- {
- rs = db.executeQuery(String sql);
- while (rs.next())
- {
- }
- db.close();
- rs = db.executeQuery(String sql2);
- while (rs.next())
- {
- }
- //db.close(); or wait for finally
- }
- catch (SQLException e)
- {
- }
- finally
- {
- db.close();
- }
你可能还会接触到以下一组try-catch语句,而且它对连接对象是比较致命的:
- try
- {
- ResultSet rs_1, rs_2;
- Rs_1 = db.executeQuery(String sql);
- while (rs.next())
- {
- rs_2 = db.executeQuery(String sql2);
- do
- {
- }while (rs_2.next())
- db.close();
- }
- //db.close(); or wait for finally
- }
- catch (SQLException e)
- {
- }
- finally
- {
- db.close();
- }
你认为这组代码是否会杀死连接对象的元凶呢?实际上,它比前面的代码更加霸道,你尽可能的缴费心肌甚至夸张的在每个角落里写上千行关闭连接的代码也无济于事。这时,我建议应该实例化两个db对象,最后分别关闭它,就能够解决问题了。
四、结语点题
还是用开篇的一句话结尾吧。当用户需要与数据库打交道时,只需要从连接池中取出一个连接对象即可,用完之后得把连接对象返还给连接池。