2010-11-18 2 views
1

싱글 톤 DAO 클래스의 연결 개체가 멤버 변수이고 레이스 조건이 발생하기 쉬운 레거시 코드를 다루고 있습니다.Java에서 thread-unsafe java.sql.Connection 객체를 사용할 수있는 가능성은 무엇입니까?

나는 잠재적 인 디자인 문제이지만 나는 자바의 jdbc 연결 객체를 다룰 때 생각할 수있는 여러 유형의 문제에 관심이 있다는 것을 알고있다.

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 정지를 삽입하고 서버 로그에서도 예외가 아니라고 발생 후

EventLoggerDAO 클래스 코드입니다.

경쟁 조건에서 다른 스레드가 보유한 연결 개체가 일관성없는 상태가 될 수 있으며 데이터를 커밋하지 못했을 것으로 생각됩니다. 연결은 연결 풀을 유지 관리하는 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

관련 문제