问题描述:对数据库的增删改查,出现“该链接已关闭”,发生概论不确定,有时成功,有时失败。
原因: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(); } } }