數據庫——“該連接已關閉”問題解決方案


問題描述:對數據庫的增刪改查,出現“該鏈接已關閉”,發生概論不確定,有時成功,有時失敗。

原因: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();
        }
    }
    
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM