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