2010-11-18 14 views
1

Je traite un code hérité où l'objet de connexion dans la classe singleton dao est une variable membre et est sujet aux conditions de course.Quelles pourraient être les possibilités d'utilisation d'un objet java.sql.Connection thread-unsafe dans java?

Je sais que c'est un problème de conception potentiel mais je suis intéressé à connaître les différents types de problèmes que l'on pourrait penser en traitant de l'objet de connexion jdbc dans Java.

Voici le code de classe 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; 
    } 
    } 
} 

problème observé:

Parfois, il arrive que la table TM_EVENT_LOG arrêts insertion et il n'y a même pas exception dans les journaux du serveur.

Je soupçonne que pendant les conditions de course, les objets de connexion détenus par des threads différents pourraient conduire à un état incohérent et pourraient ne pas être en train de valider les données. La connexion est dérivée via une source de données websphere gérant un pool de connexions.

Des idées ou des idées pour lesquelles cela pourrait se produire?

+0

Merci Carl pour le formatage du code. J'ai essayé intially mais en vain. – Tushu

+0

Vous avez des problèmes évidents et très sérieux avec les conditions de course ici. Je recommanderais de régler les problèmes que vous connaissez plutôt que d'essayer de comprendre comment/s'ils causent les symptômes observés. (Rasoir d'Occam et tout ça) –

+0

Ce que j'ai observé dans les journaux du serveur d'application, c'est qu'il y avait "java.sql.SQLException: ORA-01000: les curseurs ouverts maximum ont été dépassés" pour le code ci-dessus. Est-il obligatoire de fermer la connexion chaque fois après avoir exécuté une instruction sql même si, dans mes pensées les plus fous, je veux que cet objet conserve cette connecion sans la retourner au pool de connexions? – Tushu

Répondre

1

Tout peut arriver ici. Notez que obj_ClsPreparedStmt est une variable membre alors qu'il est utilisé comme une variable locale - il semble être un problème beaucoup plus grave que partagé Connection.

+0

Je comprends que le code ci-dessus est une erreur grave, mais ce qui m'intéresse plus, c'est de savoir comment il est possible que l'insertion s'arrête sur cette table même lorsque la connexion est en état de validation automatique? – Tushu

+0

Il peut même ne pas être lié à la connexion. Regardez le code - un thread peut écraser 'obj_ClsPreparedStmt' pendant qu'un autre thread y définit des paramètres. – axtavt

+0

D'accord, mais même alors, il doit y avoir un executeUpdate() tiré sur l'objet preparedStatement. Donc, même avec des valeurs corrompues, il aurait dû y avoir des inserts qui ont été observés comme complètement arrêtés jusqu'au redémarrage du serveur d'application suivant. – Tushu