2010-11-18 52 views
1

我正在处理遗留代码,其中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数据源派生的。

任何想法或想法,为什么这可能会发生?

+0

感谢卡尔格式化的代码。我试过但徒劳无功。 – Tushu 2010-11-18 17:47:42

+0

您在这里遇到了显而易见且非常严重的竞赛条件问题。我会建议解决你所知道的问题,而不是试图弄清楚他们是如何/是否导致观察到的症状。 (奥卡姆的剃刀和所有)。 – 2010-11-18 18:11:33

+0

我在应用程序服务器日志中观察到的是,上面的代码中存在“java.sql.SQLException:ORA-01000:超出最大打开游标数”。每次运行sql语句后关闭连接都是强制的,即使在我最疯狂的想法中,我希望这个对象保持这个连接而不返回连接池? – Tushu 2010-11-19 15:39:35

回答

1

一切都可能发生在这里。请注意0​​是一个成员变量,而它被用作局部变量 - 它似乎比共享Connection更严重的问题。

+0

我明白上面的代码是一个严重的错误,但我更感兴趣知道的是,即使连接处于自动提交状态,插入可能会停止在此表上吗? – Tushu 2010-11-18 17:59:08

+0

它甚至可能与连接无关。看代码 - 一个线程可以覆盖'obj_ClsPreparedStmt',而另一个线程正在设置参数。 – axtavt 2010-11-18 18:02:21

+0

同意,但即使如此,必须在preparedStatement对象上触发executeUpdate()。因此,即使数据已损坏,也应该插入已被观察为完全停止的插入,直到下一个应用程序服务器重新启动。 – Tushu 2010-11-18 18:20:50

相关问题