zoukankan      html  css  js  c++  java
  • [Microsoft][SQLServer 2000 Driver for JDBC]Object has been closed.

    今天在运行一个以前一直被注释掉的监听器以后不久,程序报"[Microsoft][SQLServer 2000 Driver for JDBC]Object has been closed."异常,决定查查这个原因。

    调查的结果是一个很让人想骂人的脑残问题。

    自己写了个简单的测试例子来重现这个问题:

    package com.marion.test;

    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;

    /**
     * 测试在很多访问数据库的类中频发的Object has been closed异常的发生原因
     * 
    @author Marion
     *
     
    */
    public class Test {
        
    public static void main(String[] args) {
            
    try {
                XManager xManager 
    = new XManager();
                xManager.doSQL1();
                xManager.doSQL2();
            } 
    catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    class XManager{
        Connection conn;
        
    public XManager(){
            
    try {
                String url 
    = "jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=bt_jszx;SelectMethod=Cursor";
                Class.forName(
    "com.microsoft.jdbc.sqlserver.SQLServerDriver");
                conn 
    = DriverManager.getConnection(url, "sa""sa");
            } 
    catch (Exception e) {
                e.printStackTrace();
            }
        }
        
    public void doSQL1(){
            
    try {
                PreparedStatement ps 
    = conn.prepareStatement("select * from bt_user");
                ResultSet rs 
    = ps.executeQuery();
                
    while(rs.next()){
                    
    // do nothing
                }
            } 
    catch (SQLException e) {
                e.printStackTrace();
            }
    finally{
                
    try {
                    
    if(!conn.isClosed()){
                        conn.close();
                    }
                } 
    catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
        
    public void doSQL2(){
            
    try {
                PreparedStatement ps 
    = conn.prepareStatement("select * from bt_param");
                ResultSet rs 
    = ps.executeQuery();
                
    while(rs.next()){
                    
    // do nothing
                }
            } 
    catch (SQLException e) {
                e.printStackTrace();
            }
    finally{
                
    try {
                    
    if(!conn.isClosed()){
                        conn.close();
                    }
                } 
    catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }

    }

    上面的代码在执行以后报:

    java.sql.SQLException: [Microsoft][SQLServer 2000 Driver for JDBC]Object has been closed.
    at com.microsoft.jdbc.base.BaseExceptions.createException(Unknown Source)
    at com.microsoft.jdbc.base.BaseExceptions.getException(Unknown Source)
    at com.microsoft.jdbc.base.BaseConnection.validateClosedState(Unknown Source)
    at com.microsoft.jdbc.base.BaseConnection.prepareStatement(Unknown Source)
    at com.microsoft.jdbc.base.BaseConnection.prepareStatement(Unknown Source)
    at com.marion.test.XManager.doSQL2(Test.java:57)

    at com.marion.test.Test.main(Test.java:19) 

    在老程序的许多某某Manager类里都有类似这样的多个方法共用一个Connection对象的情况,当你每次想使用这些方法都重新new一个Manager对象去调用的时候,并不会出现这个问题。但由于程序历经多年多人维护,在一段程序中重复使用同一个Manager对象的情况在所难免,于是,问题出现了。

    解决这个问题,就是在每个方法中都重新new一个Connection对象,在使用完毕后手动关闭。

    当年定义这个Manager类的人明显欠考虑,再加上后来的维护人员想当然的直接复制粘贴,最终问题爆发。

    以后在定义类的时候要注意避免这种小聪明似的做法,而在维护别人的类和使用别人定义好的类时也要多研究下内部的代码,谨记。

  • 相关阅读:
    SQL语句之奇形怪状的冷门函数
    计算累计收益
    关于SQL表字段值缺失的处理办法
    虚拟机移植到另一台机器
    分分钟搞懂rank() over(partition by)的使用
    分分钟搞懂union与union all
    【转】10分钟就能学会的.NET Core配置
    【转】依赖注入的威力,.NET Core的魅力:解决MVC视图中的中文被html编码的问题
    【转】Asp.Net Core2.0获取客户IP地址,及解决发布到Ubuntu服务器获取不到正确IP解决办法
    【转】在.net Core 中像以前那样的使用HttpContext.Current
  • 原文地址:https://www.cnblogs.com/mabaishui/p/2102838.html
Copyright © 2011-2022 走看看