問題描述:對數據庫的增刪改查,出現“該鏈接已關閉”,發生概論不確定,有時成功,有時失敗。
原因: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(); } } }
