去年看他的视频时没觉得有什么问题,那时自己也不懂。
今天忽然想起这个问题,做了个小小的测试,结果发现他的方法好像有错误。
现来请教下大家。
 //释放链接  
    public static void free(ResultSet rs, Statement st, Connection conn) {  
        try {  
            if (rs != null)  
                rs.close();  
        } catch (SQLException e) {  
            e.printStackTrace();  
        } finally {  
            try {  
                if (st != null)  
                    st.close();  
            } catch (SQLException e) {  
                e.printStackTrace();  
            } finally {  
                if (conn != null)  
                    try {  
                        conn.close();  
                    } catch (SQLException e) {  
                        e.printStackTrace();  
                    }  
                }  
            }  
        }  
    }  
      
这是他的源码。
http://longdechuanren.iteye.com/blog/632358
这个博客不是他本人的,但代码是根据他的视频整理的。
我先在mysql把最大连接数设为1.
然后把insert()方法执行3次,执行第三次的时候会报错(如果只执行2次,不报错),提示com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Data source rejected establishment of connection,  message from server: "Too many connections"
顺便问下,为什么不是执行第2次的时候报错?
public void insert(String name, String passwd) {
try {
conn = DriverManager.getConnection(dbUrl, dbUser, dbPassword);
ps = conn
.prepareStatement("insert into user(username,password) values(?,?)");
ps.setString(1, name);
ps.setString(2, passwd);
ps.executeUpdate(); } catch (Exception e) {
System.out.println(e.toString());
}
}接着,我把他的free()方法插在第2次insert()方法后执行。我的设想是,已经关闭了连接,再执行第三次,就相当于开了新连接执行第一次,应该不会报错吧。可是执行结果依然报错,too many connections。
=================================
刚好前段时间有人在csdn问,java中交换两个数的方法是什么 api有吗?http://topic.csdn.net/u/20110307/21/ced90e4d-6d64-4709-b157-5be2d32ea0da.html
于是这时,我把他的 free(ResultSet rs, Statement st, Connection conn)的参数去掉,直接用free()。
运行,代码成功运行。
特别说明:如有兴趣,请自己测试下。
分2种情况:
把数据库操作的insert方法和主函数放一个类;再运行 free(有参数)和free();
把数据库操作的insert方法和主函数分开放在两个类;再运行free(有参)和free()。
==============================================
实验结果,李勇写错了。数据库关闭连接的方法里,不应该带参数。
即应该用free(),而不要用 free(ResultSet rs, Statement st, Connection conn)如果我的实验有漏洞或根本就是我错了,或我和李勇都错,请狂喷并说明原因

解决方案 »

  1.   

    分2种情况:
    把数据库操作的insert方法和主函数放一个类;再运行 free(有参数)和free();
    把数据库操作的insert方法和主函数分开放在两个类;再运行free(有参)和free()。
    ================================
    在第一种情况,好像结果是成功了,但是其实是不成功的。
    所以,请你把free(有参数)和free()改为如下:增加了=null,并增加了打印信息。
    try {
    if (rs != null) {
    System.out.println(rs);
    rs.close();
    rs = null;
    } else {
    System.out.println("rs = null");
    }
    } catch (SQLException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    } finally {
    try {
    if (ps != null) {
    System.out.println(ps);
    ps.close();
    ps = null;
    } else {
    System.out.println("ps = null");
    }
    } catch (SQLException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    } finally {
    try {
    if (conn != null) {
    System.out.println(conn);
    conn.close();
    conn = null;
    } else {
    System.out.println("conn = null");
    }
    } catch (SQLException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }
    }
    这时,你可以很明显地看到,free(有参数)方法执行的不成功了。
      

  2.   

    你最好把你调用的insert的方法放上来,不然真不好说谁错了
      

  3.   

    不,实验结果是,free()不能带参数,并且要让起=null才算真正的关闭
      

  4.   

    额,我收回4楼的话。不设置=null也关闭了
      

  5.   

    因为你的mysql安装目录下的my.ini中设定的并发链接数太少你循环链接数据库的时候前面的还没关呢后面的就来了所以是 "too many connections"这是MySQL的问题不是那个老师的问题看程序,写得还挺规范吧。
      

  6.   

    第一题;代码写的也够差的了,真的以为是在盖楼啊;直接 try {
    if (rs != null) {
    rs.close();
    rs = null;
    }
    if (stmt != null) {
    stmt.close();
    stmt = null;
    }
    if (conn != null) {
    conn.close();
    conn = null;
    }
    } catch (SQLException ac) {
    ac.printStackTrace();
    }
      

  7.   

    try {
    }catch(){
    }不要整那么多
      

  8.   

    请问楼上7楼的
    rs.close() 抛出呢
    求教咋处理
      

  9.   

    我是故意设置并发连接小。
    就是为了证明,我的free()已经彻底释放了连接。
      

  10.   

    其实,说到底这个问题就是java参数是值调用的问题。
    比如,你在测试类调用insert()方法。
    public void insert(String name, String passwd) {
            try {
                conn = DriverManager.getConnection(dbUrl, dbUser, dbPassword);
                ps = conn
                        .prepareStatement("insert into user(username,password) values(?,?)");
                ps.setString(1, name);
                ps.setString(2, passwd);
                ps.executeUpdate();        } catch (Exception e) {
                System.out.println(e.toString());
            }
        }
    那么你在测试类根本无需声明conn,ps,你只需在测试类中声明个rs来存放insert返回的resultset就行了。
    那么你在调用free(ResultSet rs, Statement st, Connection conn);的时候,
    由于你的当前类没有st,conn的声明,那程序是不是会报错?
    于是你在测试类中再声明st,conn,那么,free(ResultSet rs, Statement st, Connection conn)其实close的是你在测试类中声明的st,conn,rs
      

  11.   

    我无法想象你的思路,不加参数,那么请问楼主你的free方法之中,如何获取dao.impl层的rs,pstmt,conn?
      

  12.   

    我明白了。去年那时真是too young too naive啊
      

  13.   

    不明白你们为什么要先放在try-catch里面在来判断if-elsepublic static void free(ResultSet rs,Statement ps,Connection conn){      if(null!=rs){
               try{
                  rs.close();
                  rs=null;
               }catch(Exception e){
               }
          }      if(null!=ps){
               try{
                  ps.close();
                  ps=null;
               }catch(Exception e){
               }
          }      if(null!=conn){
               try{
                  conn.close();
                  conn=null;
               }catch(Exception e){
               }
          }}