Java 连接关闭不会关闭Tomcat中的连接

Java 连接关闭不会关闭Tomcat中的连接,java,sql,sql-server,tomcat,Java,Sql,Sql Server,Tomcat,在我在Tomcat上运行的java web项目中,2天后有4000多个休眠连接(我用sp_who命令检查了它们)。在完成数据库作业后,我确实会关闭每个语句、结果集和连接。我使用下面的模板处理数据库内容 try{ this.openConnection(); this.createStatement(); // things ... this.cleanResources(); }catch (SQLExcepti

在我在Tomcat上运行的java web项目中,2天后有4000多个休眠连接(我用sp_who命令检查了它们)。在完成数据库作业后,我确实会关闭每个语句、结果集和连接。我使用下面的模板处理数据库内容

    try{
        this.openConnection();
        this.createStatement();

        // things ...

        this.cleanResources();
    }catch (SQLException e){
        this.cleanResources();
        e.printStackTrace();
    }

    public void cleanResources() {
    try {
        if (this.rs != null) {
            rs.close();
            this.rs = null;
        }
        if (this.stmt != null) {
            stmt.close();
            this.stmt = null;
        }
        if (this.conn != null) this.closeConnection();
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if (this.conn != null) this.closeConnection();
    }
}

   public void closeConnection() {
    try {
        if (this.conn != null)
            this.conn.close();
        this.isOpen = false;
    } catch (Exception e) {
        e.printStackTrace();
    }
}

public void createStatement() {
    try {
        if (!this.isOpen) this.openConnection();
        this.stmt = this.conn.createStatement();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

public void openConnection() {
    try {
        this.conn = ds.getConnection(); // ds is a javax.sql.DataSource instance
        this.isOpen = true;
    } catch (Exception e) {
        e.printStackTrace();
    }
}
每次sql代码运行后,处于休眠状态的行数都会增加,数据库的运行速度也会变慢。为什么会这样?我怎么能在完成连接后完全杀死它?是否真的是休眠连接使我的SQL Server变慢了

以下是我的Tomcat配置(在context.xml中):


清洁连接的代码/模式有缺陷:

try {
    this.openConnection();
    this.createStatement();

    // things ...

    this.cleanResources();
} catch (SQLException e){
    this.cleanResources();
    e.printStackTrace();
}
如果“things”抛出的异常不是
SQLException
或子类,则不会关闭连接

如果应该:

try {
    this.openConnection();
    this.createStatement();

    // things ...

    this.cleanResources();
} catch (SQLException e) {
    e.printStackTrace();
} finally {
    this.cleanResources();
}
那么这个,

public void cleanResources() {
    try {
        if (this.rs != null) {
            rs.close();
            this.rs = null;
        }
        if (this.stmt != null) {
            stmt.close();
            this.stmt = null;
        if (this.conn != null) this.closeConnection();
    } catch (Exception e) {
        e.printStackTrace();
    }
}
如果
rs.close()
stmt.close()
引发异常,则连接未关闭

应该是这样的:

public void cleanResources() {
    try {
        if (this.rs != null) {
            rs.close();
            this.rs = null;
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    try {
        if (this.stmt != null) {
            stmt.close();
            this.stmt = null;
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    try {
        if (this.conn != null) this.closeConnection();
    } catch (Exception e) {
        e.printStackTrace();
    }
}
在某些情况下,这些缺陷都可能导致数据库连接泄漏

另一种可能性是,代码中的某个地方没有遵循(有缺陷的)模式

我认为你需要仔细阅读以下内容:

  • Java 7+“尝试使用资源”支持
  • Java1.0+“尝试……最终”

还值得注意的是,以下做法是不好的:

  • 捕获异常。。。在大多数情况下
  • 挤压异常(即捕捉并静默继续)。。。在大多数情况下
  • 在整个代码中分散对printStackTrace的调用

强烈建议您放弃该代码,转而使用try with resources。在字段中保留
语句
结果集
是不合适的。--但是,如果你坚持这种逻辑,至少你需要把
cleanResources()
放在
finally
块中。既然我们看不到
openConnection()
closeConnection()
方法做什么,我们怎么说你做得对呢?@Andreas对不起,我错过了那个,现在编辑了。@Andreas我现在要尝试在finally block中执行它。@Andreas在finally block中执行它没有任何区别,仍然处于睡眠状态的连接数正在减少。我观察到,即使没有例外,睡眠连接数也在增加。我只是在finally block中用清洁资源试了一下,但没有任何区别。在这种情况下,你做得不对。“最终”或“尝试资源”方法有效。。。如果你做得正确。如果你真的需要帮助调试你的代码,你需要提供一个MCVE(重点放在M…上,以便最小化)
public void cleanResources() {
    try {
        if (this.rs != null) {
            rs.close();
            this.rs = null;
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    try {
        if (this.stmt != null) {
            stmt.close();
            this.stmt = null;
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    try {
        if (this.conn != null) this.closeConnection();
    } catch (Exception e) {
        e.printStackTrace();
    }
}