2010-11-18 51 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

相關問題