我正在处理遗留代码,其中singleton dao类中的连接对象是成员变量并且容易出现竞争条件。在java中使用线程不安全的java.sql.Connection对象有什么可能?
我知道这是一个潜在的设计问题,但是我有兴趣了解在处理java中的jdbc连接对象时可以考虑的不同类型的问题。
以下是EventLoggerDAO类代码:
package com.code.ref.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import com.code.ref.utils.common.DBUtil;
import com.code.ref.utils.common.PCMLLogger;
public class EventLoggerDAO {
private static EventLoggerDAO staticobj_EventLoggerDAO;
private Connection obj_ClsConnection;
private PreparedStatement obj_ClsPreparedStmt;
private EventLoggerDAO() {
try {
obj_ClsConnection = DBUtil.getConnection();
} catch (Exception e) {
PCMLLogger.logMessage(EventLoggerDAO.class, "EventLoggerDAO()", "Some problem in creating db connection:" + e);
}
}
public static synchronized EventLoggerDAO getInstance() {
if (staticobj_EventLoggerDAO == null) {
synchronized (EventLoggerDAO.class) {
if (staticobj_EventLoggerDAO == null)
staticobj_EventLoggerDAO = new EventLoggerDAO();
}
}
return staticobj_EventLoggerDAO;
}
public void addEvent(String sName, String sType, String sAction, String sModifiedBy) throws Exception {
StringBuffer sbQuery = new StringBuffer();
sbQuery.append("INSERT INTO TM_EVENT_LOG (NAME, TYPE, ACTION, MODIFIED_BY) ").append("VALUES (?, ?, ?, ?) ");
if(obj_ClsConnection == null)
obj_ClsConnection = DBUtil.getConnection();
obj_ClsPreparedStmt = obj_ClsConnection.prepareStatement(sbQuery.toString());
obj_ClsPreparedStmt.setString(1, sName);
obj_ClsPreparedStmt.setString(2, sType);
obj_ClsPreparedStmt.setString(3, sAction);
obj_ClsPreparedStmt.setString(4, sModifiedBy);
obj_ClsPreparedStmt.executeUpdate();
if (obj_ClsPreparedStmt != null) {
obj_ClsPreparedStmt.close();
obj_ClsPreparedStmt = null;
}
}
}
问题观察:
有时候碰巧表TM_EVENT_LOG
停止插入并没有例外,甚至在服务器日志中。
我怀疑在竞争条件下,由不同线程持有的连接对象可能会导致不一致的状态,也可能不会提交数据。连接是通过维护连接池的websphere数据源派生的。
任何想法或想法,为什么这可能会发生?
感谢卡尔格式化的代码。我试过但徒劳无功。 – Tushu 2010-11-18 17:47:42
您在这里遇到了显而易见且非常严重的竞赛条件问题。我会建议解决你所知道的问题,而不是试图弄清楚他们是如何/是否导致观察到的症状。 (奥卡姆的剃刀和所有)。 – 2010-11-18 18:11:33
我在应用程序服务器日志中观察到的是,上面的代码中存在“java.sql.SQLException:ORA-01000:超出最大打开游标数”。每次运行sql语句后关闭连接都是强制的,即使在我最疯狂的想法中,我希望这个对象保持这个连接而不返回连接池? – Tushu 2010-11-19 15:39:35