2010-11-18 5 views
1

私はシングルトンダオクラスの接続オブジェクトがメンバー変数で競争条件になりがちなレガシーコードを扱っています。スレッドセーフでないjava.sql.Connectionオブジェクトをjavaで使用する可能性はありますか?

私はこれが潜在的な設計上の問題だと知っていますが、私は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

コードをフォーマットするためのCarlさんに感謝します。私はintiallyしかし無駄にしようとした。 – Tushu

+0

ここで競争条件には明らかで非常に深刻な問題があります。あなたが知っている問題を修正することをお勧めします。 (オッカムのカミソリとそのすべて)。 –

+0

上記のコードで、アプリケーション・サーバーのログに「java.sql.SQLException:ORA-01000:maximum open cursors exceeded」というメッセージが表示されました。私の荒々しい考えでも、このオブジェクトを接続プールに戻さずにこの接続を保持したい場合でも、SQL文を実行した後に毎回接続を閉じることは必須ですか? – Tushu

答えて

1

すべてがここで起こります。 obj_ClsPreparedStmtはメンバ変数ですが、ローカル変数として使用されています - これは共有されたConnectionよりもはるかに深刻な問題であるようです。

+0

私は上記のコードが深刻な大失敗であると理解していますが、私が知ることに興味があるのは、接続が自動コミット状態にあっても挿入がこのテーブルで停止する可能性があることです。 – Tushu

+0

接続に関連しないこともあります。コードを見てください。一つのスレッドが 'obj_ClsPreparedStmt'を上書きし、別のスレッドがその上にパラメータを設定しています。 – axtavt

+0

合意されていますが、それでもなおpreparedStatementオブジェクトに対してexecuteUpdate()が発生している必要があります。したがって、破損した値であっても、次のアプリケーションサーバーが再起動するまで完全に停止していることが観察された挿入があったはずです。 – Tushu

関連する問題