2014-11-12 3 views
0

은 오랫동안 독자로 여기에 있었고 이제는 내 머리를 얻을 수없는 문제가 있습니다.정적 클래스/메소드에서 메서드 수준 연결을 사용하는 풀링 된 db 액세스가 안전한가요?

액세스하기 쉽고 개체 생성 오버 헤드를 절약하기 위해 데이터베이스 액세스를 구현하는 정적 클래스가 있습니다. 사용 된 JVM 구현은 Tomcat이고 연결 풀링을 위해서는 org.apache.commons.dbcp가 사용됩니다.

여기서는 스레드 안전성, 힙 및 스택에 대해 많이 읽었지만 정적 클래스에 대한 여러 메서드 호출이 서로 간섭하지 않으면 확실한 결론을 내릴 수 없습니다. 내가 읽은 대부분의 주제는 내가 간과 한 함의가있는 정적 인 것들을 사용하는 동안 인스턴스 메소드를 다루고있다.

변수 연결, 문, 결과 집합이 메서드 수준에 있기 때문에 모든 것을 올바르게 이해했다면 각 함수 호출은 힙의 고유 한 개체에 대한 스택의 고유 한 참조를 가져야하며 다중 메소드 호출은 서로 간섭합니다.

맞지 않습니까? 어떤 도움을 주시면 감사하겠습니다.

은 (단축) 코드는

입니다 :

public class DBQuery{ 


private static String pathToDataSource = ""; 
private static javax.naming.Context cxt = null; 
private static javax.sql.DataSource ds = null; 


private static void getDataSource() throws Exception { 
    if(pathToDataSource.equals("")){ pathToDataSource = Config.getParam("PathToDataSource"); } 
    cxt = new javax.naming.InitialContext(); 
    ds = (javax.sql.DataSource) cxt.lookup(pathToDataSource); 
} 


private static Connection connect() throws Exception { 
    if(ds==null){ getDataSource(); } 
    return ds.getConnection(); 
} 


public static Vector doDBquery(String querystring) throws Exception { 
    Vector retVec = new Vector(); 
    Connection connection = null; 
    Statement statement = null; 
    ResultSet resultset = null; 
    try { 
    connection = getConnection(); 
    statement = connection.createStatement(); 
    resultset = statement.executeQuery(querystring);  
    ... 
    } catch(Exception e) { 
    ... 
    } finally { 
    myFinallyBlock(resultset, statement, connection); 
    } 
    return retVec; 
} 


// more methods like doDBInsert() following, hence closure in separate myFinallyBlock 


private static void myFinallyBlock(ResultSet resultset, Statement statement, Connection connection) { 
    try { 
    if (resultset != null) resultset.close(); 
    } catch (SQLException e) { resultset = null; } 
    try { 
    if (statement != null) statement.close(); 
    } catch (SQLException e) { statement = null; } 
    try { 
    if (connection != null) connection.close(); 
    } catch (SQLException e) { connection = null; } 
} 


} //close class 

답변

0

당신이 그 안에 공유 변수를 사용하여 때까지 그래, 즉, 동시성 문제가 없습니다 올바른 방법 내부에 항상 스레드있다 "비 저장 개체 -안전한."

편집)

서블릿은 그것의 아주 좋은 예입니다. 코드를 안전하게 만들기위한

난 당신이 추적 할 것을 권장합니다 :

private static Connection connect() throws Exception { 
    if (ds == null) { 
    synchronized (Connection.class) { 
     if (ds == null) { 
     getDataSource(); 
     } 
    } 
    } 
    return ds.getConnection(); 
} 
+0

좋은 소식이 될 것이지만, 무 상태 객체로 정적 클래스 수를합니까? 나에게는 매우 비슷하지만 실제로 인스턴스화 된 객체는없는 것으로 보입니다. 그것은 다른 주제가 항상 인스턴스화 가능한 클래스에 관한 것이기 때문에 내 문제입니다. –

+0

제안을 읽어 주셔서 감사합니다. 데이터 소스 초기화는 다른 사용자가 동시에 액세스 할 수없는 한 스레드 만 실행할 수 있습니다. Connection.class를 사용하면 다른 스레드가 다른 메소드를 호출 할 수 있습니다. –

+0

아니요, 연결 초기화 중에 전체 클래스를 잠글 것입니다.하지만 연결이 없으면 클래스가 유용하지 않으므로 시간이 많이 걸리지 않으며 초기화 후에도 성능에 영향을주지 않고 작동합니다. 그러나 초기화를위한 성능에 대해 신경 쓰는 경우 정적 최종 설정으로 연결을 만들 수 있고 정적 초기화 블록에 설정할 수 있습니다. – Maksym