Java代码不关闭MySQL连接,尽管按相反顺序关闭资源

Java代码不关闭MySQL连接,尽管按相反顺序关闭资源,java,mysql,tomcat,tomcat6,Java,Mysql,Tomcat,Tomcat6,下面的代码似乎无法正确关闭MySQL连接,即使我们以相反的顺序关闭资源。当再次运行此代码时,它似乎重用了同一个MySQL进程线程,您可以在下面查看与实际运行的MySQL查询(从MySQL.general_log中提取)交叉引用的MySQL进程列表 我们做错了什么 我们正在使用Tomcat6.0(不问,你不想知道)和Java1.6.05 代码: String cat_name = request.getParameter("category"); if (cat_name != null) {

下面的代码似乎无法正确关闭MySQL连接,即使我们以相反的顺序关闭资源。当再次运行此代码时,它似乎重用了同一个MySQL进程线程,您可以在下面查看与实际运行的MySQL查询(从MySQL.general_log中提取)交叉引用的MySQL进程列表

我们做错了什么

我们正在使用Tomcat6.0(不问,你不想知道)和Java1.6.05

代码:

String cat_name = request.getParameter("category");
if (cat_name != null) {
    DBWrapper db = new DBWrapper();
    ResultSet rs = null;
    try {     
      String parent_cat_name = null;      
      rs = db.executeQuery("SELECT cat_name FROM CATEGORY WHERE cat_code = (SELECT cat_main_code FROM category WHERE cat_name='" + cat_name + "')" );
      if (rs != null && rs.first()) {
        parent_cat_name = rs.getString("cat_name");
        page_title = title_prefix + parent_cat_name + " > " + cat_name;
      } else {
        page_title = title_prefix + cat_name;
      }
    } catch (Exception e) {
      System.out.println(e);
    } finally {
       try {
         if (rs != null) rs.close();
         if (db != null) db.closeConnection();
       } catch (Exception e) {
         System.out.println(e);     
       }
    }
}
    public class DBWrapper {
        private Connection con = null;
        private Statement stmt = null;
        private DataSource ds;
        private HashMap tables;

  public DBWrapper(){

        try {
            Context ctx = new InitialContext();
            if (ctx == null)
                throw new Exception("Boom - No Context");
            ds = (DataSource) ctx.lookup("java:comp/env/jdbc/eDB");
            if (ds != null) {
                con = ds.getConnection();
            }
            tables = new HashMap();
            loadMappings();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

        (other stuff)

        public void closeConnection(){
            try {
                if (stmt != null) stmt.close();
                if (con != null) con.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
DBWrapper.java:

String cat_name = request.getParameter("category");
if (cat_name != null) {
    DBWrapper db = new DBWrapper();
    ResultSet rs = null;
    try {     
      String parent_cat_name = null;      
      rs = db.executeQuery("SELECT cat_name FROM CATEGORY WHERE cat_code = (SELECT cat_main_code FROM category WHERE cat_name='" + cat_name + "')" );
      if (rs != null && rs.first()) {
        parent_cat_name = rs.getString("cat_name");
        page_title = title_prefix + parent_cat_name + " > " + cat_name;
      } else {
        page_title = title_prefix + cat_name;
      }
    } catch (Exception e) {
      System.out.println(e);
    } finally {
       try {
         if (rs != null) rs.close();
         if (db != null) db.closeConnection();
       } catch (Exception e) {
         System.out.println(e);     
       }
    }
}
    public class DBWrapper {
        private Connection con = null;
        private Statement stmt = null;
        private DataSource ds;
        private HashMap tables;

  public DBWrapper(){

        try {
            Context ctx = new InitialContext();
            if (ctx == null)
                throw new Exception("Boom - No Context");
            ds = (DataSource) ctx.lookup("java:comp/env/jdbc/eDB");
            if (ds != null) {
                con = ds.getConnection();
            }
            tables = new HashMap();
            loadMappings();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

        (other stuff)

        public void closeConnection(){
            try {
                if (stmt != null) stmt.close();
                if (con != null) con.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
MySQL进程列表和查询:

String cat_name = request.getParameter("category");
if (cat_name != null) {
    DBWrapper db = new DBWrapper();
    ResultSet rs = null;
    try {     
      String parent_cat_name = null;      
      rs = db.executeQuery("SELECT cat_name FROM CATEGORY WHERE cat_code = (SELECT cat_main_code FROM category WHERE cat_name='" + cat_name + "')" );
      if (rs != null && rs.first()) {
        parent_cat_name = rs.getString("cat_name");
        page_title = title_prefix + parent_cat_name + " > " + cat_name;
      } else {
        page_title = title_prefix + cat_name;
      }
    } catch (Exception e) {
      System.out.println(e);
    } finally {
       try {
         if (rs != null) rs.close();
         if (db != null) db.closeConnection();
       } catch (Exception e) {
         System.out.println(e);     
       }
    }
}
    public class DBWrapper {
        private Connection con = null;
        private Statement stmt = null;
        private DataSource ds;
        private HashMap tables;

  public DBWrapper(){

        try {
            Context ctx = new InitialContext();
            if (ctx == null)
                throw new Exception("Boom - No Context");
            ds = (DataSource) ctx.lookup("java:comp/env/jdbc/eDB");
            if (ds != null) {
                con = ds.getConnection();
            }
            tables = new HashMap();
            loadMappings();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

        (other stuff)

        public void closeConnection(){
            try {
                if (stmt != null) stmt.close();
                if (con != null) con.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

Tomcat数据库配置:

Resource name="jdbc/eDB" auth="Container" type="javax.sql.DataSource" maxActive="100" maxIdle="30" maxWait="10000" username="***" password="****" driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/ce?autoReconnect=true" /> 

你能分享(其他东西)的代码吗

您是如何获得连接的?从数据库池?我们需要看看什么是具体的连接类才能提供帮助


我的理论是,您的具体连接类可能无法正确释放连接。

谢谢!但是对rs.close()、stmt.close()和con.close()的调用不是关闭连接所需的全部吗?稍后将发布更多信息…刚刚用dbwrapper.java中的更多信息更新了问题。谢谢你的帮助!如果您有子类连接类,并且它没有正确关闭连接,那么您可能会遇到问题。但这只是我的理论。你所拥有的是正确的收尾顺序。另外,您在哪里创建语句?您是否看到任何PrintStackTrace显示?我看到您使用的是数据源(我相信是Tomcat数据源)。当您调用
conn.close()
时,并不意味着您与db的连接被关闭。根据oracle文档,这就是所发生的“立即释放此连接对象的数据库和JDBC资源,而不是等待它们自动释放”。还要检查tomcat数据源配置。我怀疑这是某种池配置错误,因此我建议重新分解代码,因为
DBWrapper
类应该是幂等的。由于
DBWrapper
的使用者没有获取连接并创建语句,使用者不应负责关闭连接和语句。控制台中没有出现错误?没有错误。只有当我们的连接用完时,bc的连接才不会被关闭。