2010-11-18 5 views
1

Ich habe es mit einem Legacy-Code zu tun, bei dem das Verbindungsobjekt in der Singleton-Dao-Klasse eine Member-Variable ist und anfällig für Rennbedingungen ist.Was könnten die Möglichkeiten sein, ein Thread-unsicheres java.sql.Connection-Objekt in Java zu verwenden?

Ich weiß, dass dies ein potenzielles Designproblem ist, aber ich bin daran interessiert, über die verschiedenen Arten von Problemen zu wissen, die man sich beim Umgang mit dem jdbc-Verbindungsobjekt in Java vorstellen kann.

Es folgt der EventLoggerDAO Klassencode:

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; 
    } 
    } 
} 

Problem beobachtet:

Manchmal kommt es vor, dass die Tabelle TM_EVENT_LOG stoppt das Einfügen und es gibt nicht einmal Ausnahme in den Server-Logs.

Ich vermute, dass die Verbindungsobjekte, die von verschiedenen Threads gehalten werden, unter Wettbewerbsbedingungen möglicherweise zu einem inkonsistenten Zustand führen und die Daten möglicherweise nicht übertragen. Die Verbindung wird über eine Websphere-Datenquelle abgeleitet, die einen Verbindungspool verwaltet.

Irgendwelche Gedanken oder Ideen, warum dies passieren könnte?

+0

Danke Carl für die Formatierung des Codes. Ich habe versucht, aber vergeblich. – Tushu

+0

Sie haben hier offensichtlich und sehr ernsthafte Probleme mit den Rennbedingungen. Ich würde empfehlen, die Probleme, die Sie kennen, zu beheben, anstatt zu versuchen herauszufinden, wie/ob sie die beobachteten Symptome verursachen. (Ockhams Rasiermesser und all das). –

+0

Was ich von den Logs des Anwendungsservers beobachtet habe, ist, dass es "java.sql.SQLException: ORA-01000: maximale offene Cursor überschritten" für den obigen Code gab. Ist es zwingend notwendig, die Verbindung jedes Mal nach dem Ausführen einer SQL-Anweisung zu schließen, auch wenn ich in meinen kühnsten Gedanken möchte, dass dieses Objekt diese Verbindung behält, ohne sie in den Verbindungspool zurückzugeben? – Tushu

Antwort

1

Hier kann alles passieren. Beachten Sie, dass obj_ClsPreparedStmt eine Membervariable ist, während es als eine lokale Variable verwendet wird - es scheint ein viel ernsthafteres Problem zu sein als Connection.

+0

Ich verstehe, dass der obige Code ein schwerwiegender Fehler ist, aber was ich mehr interessiert zu wissen ist, wie es möglich sein könnte, dass die Einfügung auf dieser Tabelle stoppt, selbst wenn die Verbindung im Auto-Commit-Zustand ist? – Tushu

+0

Möglicherweise ist es nicht einmal mit der Verbindung verbunden. Sehen Sie sich den Code an - ein Thread kann 'obj_ClsPreparedStmt' überschreiben, während ein anderer Thread Parameter darauf setzt. – axtavt

+0

Vereinbar, aber auch dann muss eine executeUpdate() auf dem preparedStatement-Objekt ausgelöst werden. Also, selbst mit korrupten Werten sollte es Inserts gegeben haben, die bis zum nächsten Neustart des Anwendungsservers als vollständig gestoppt betrachtet wurden. – Tushu

Verwandte Themen