zoukankan      html  css  js  c++  java
  • 数据库——“该连接已关闭”问题解决方案

    问题描述:对数据库的增删改查,出现“该链接已关闭”,发生概论不确定,有时成功,有时失败。

    原因:Connection 是线程不安全的,当将Connection设置为全局变量,若有一个线程正将该连接close,而另一线程正在访问,则会出现“该链接已关闭”的错误。

    解决方案:将Connection设置为局部变量,或每次调用时从新开一个连接。(若嫌速度慢,可以考虑使用连接池)。

    修改后的代码:

    package common.DaoImplement;
    
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    
    import org.w3c.dom.Document;
    import org.w3c.dom.Element;
    import org.w3c.dom.NodeList;
    
    import common.DaoInterface.IConnectionDatabase;
    import common.tool.ReaderXmlConfig;
    
    public class ConDatabaseBySqlServerImp implements IConnectionDatabase
    {
        private String driver;
        private String url;
        private String username;
        private String password;
        private Connection con = null;
        private Statement st = null;
        ResultSet rs  = null;
        /**
         * 通过读取配置文件初始化参数
         * ReaderXmlConfig,这是一个单例的类,用于得到Config.xml配置文件
         */
        public void initialize()
        {
            Document doc = ReaderXmlConfig.getInstance();
            NodeList dbs = doc.getElementsByTagName("db");
            Element db = (Element)dbs.item(0);
            String driver = db.getElementsByTagName("driver").item(0).getFirstChild().getNodeValue();
            String url = db.getElementsByTagName("url").item(0).getFirstChild().getNodeValue();
            String username = db.getElementsByTagName("username").item(0).getFirstChild().getNodeValue();
            String password = db.getElementsByTagName("password").item(0).getFirstChild().getNodeValue();
            
            this.driver = driver;
            this.url = url;
            this.username = username;
            this.password = password;
    
        }
        
        /**
         * 构造方法
         * 加载数据库
         */
        public ConDatabaseBySqlServerImp(){
            initialize();
            try {
                Class.forName(driver);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
        
        /**
         *对外提高Connection的接口
         *在此没有直接使用上面定义的con,而是重新定义了一个conn,即每次外部调用getConnection()方法,都将返回一个新的连接(注意在使用后关闭)
         *若此处直接是使用con,可能导致多线程并发访问,导致出错。
         */
        @Override
        public  Connection getConnection() {
            Connection conn = null;
            try {
                    conn = DriverManager.getConnection(url, username, password);
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            return conn;
        }
        
        /**
         * 用于内部的使用
         */
        private void getCon()
        {
            if(con == null)
            {
                try {
                    con = DriverManager.getConnection(url, username, password);
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
        
        /**
         * 执行查询
         */
        @Override
        public ResultSet executeSql(String sql) {
            getCon();
            try {
                st = con.createStatement();
                rs = st.executeQuery(sql);
            } catch (SQLException e) {
                e.printStackTrace();
            }
            return rs;
        }
    
        /**
         * 执行删除,修改等无返回值的语句
         */
        @Override
        public Boolean executeUpdate(String sql) {
            getCon();
            try {
                st = con.createStatement();
                st.executeUpdate(sql);            
            } catch (SQLException e) {
                e.printStackTrace();
                return false;
            }
            return true;
        }
    
        /**
         * 关闭连接
         */
        @Override
        public void closeConnection() {
            try{
                if(rs != null)
                {
                    rs.close();
                    rs = null;
                }
                if(st != null)
                {
                    st.close();
                    st = null;
                }
                if(con != null)
                {
                    con.close();
                    con = null;
                }
            }catch(SQLException e)
            {
                e.printStackTrace();
            }
        }
        
    }
  • 相关阅读:
    gain 基尼系数
    luogu P5826 【模板】子序列自动机 主席树 vector 二分
    牛客挑战赛39 树与异或 离线 树上莫队 树状数组 约数
    4.22 省选模拟赛 三元组 manacher 回文自动机
    4.22 省选模拟赛 最优价值 网络流 最大权闭合子图
    4.18 省选模拟赛 消息传递 树剖 倍增 线段树维护等比数列
    luogu P4008 [NOI2003]文本编辑器 splay 块状链表
    牛客挑战赛39 密码系统 后缀数组
    luogu P1526 [NOI2003]智破连环阵 搜索+最大匹配+剪枝
    luogu P4095 [HEOI2013]Eden 的新背包问题 多重背包 背包的合并
  • 原文地址:https://www.cnblogs.com/ITinfo/p/3462782.html
Copyright © 2011-2022 走看看