2012-04-05 1 views
1

내 Java weblogic 포털 응용 프로그램의 특정 세부 사항을 Oracle DB에 기록하기 위해 데이터베이스 로깅을 구현했습니다. 이 때문에 연결 풀링을 사용하여 jdbc를 저장 프로 시저 호출에 사용합니다.jdbc 호출에서 커밋을 줄이고 대량 레코드를 한 번에 삽입 하시겠습니까?

나는 연결 개체를 가져 와서 SP를 호출하는 정적 java 메서드 logService가 있습니다. 이 logservice 메서드는 내 Java 응용 프로그램의 다른 위치에서 호출되며 관련 세부 정보는 int에서 SP 호출에 전달되는 매개 변수로 전달됩니다.

따라서 포털에 액세스하는 각 사용자에 대해 약 10-20 개의 logservice 메소드 호출이 있습니다. 그래서 10-20 SP 통화를하고 SP에 전화 할 때마다 커밋해야합니다.

하지만 문제는 내 DBA가 커밋 빈도가 높기 때문에 각 트랜잭션에 커밋하지 말고 inturn이 한 번에 10-20 개의 트랜잭션을 모두 커밋하도록 권장했습니다. 어떻게해야합니까? 명확하지 않으면 샘플 코드를 게시 할 수 있습니다. 다음과 같이

그래, 난 이미 다음과 같이

public final class RequestFilter implements Filter{ 

public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) { 
try { 
     ((HttpServletResponse) response).sendRedirect(redirectUrl); 

    if (chain != null) { 
      chain.doFilter(request, response); 
     } 
    } 
finally { // commit transaction here } 
} 
} 

redirectURL로 리디렉션 후, 나는 내 응용 프로그램에서 많은 장소에서 logservice를 호출하고, 내 웹 응용 프로그램

DBLog.logService(param1, param2); // static method call 

이 필터를 데 logservice는 연결 풀링 객체를 사용하여 SP에 prepareCall을 수행합니다. 아래에 간단한 샘플 코드를 제공하고 있습니다.

public static void logService(String param1, String param2) { 

try { 

con=getConnection(); 
stmt = con.prepareCall("{call DB_LOG_SP (?, ?}"); 
stmt.setString(1, param1); 
stmt.setString(2, param2); 
stmt.execute(); 
stmt.close(); 
}finally { 
      stmt.close(); 
      con.close(); 
     } 
} 

SP 호출 후 연결을 닫을 때 doFilter 메서드 내에서 {{} 블록으로 트랜잭션을 커밋하는 방법은 무엇입니까?

필터 접근 -

public class DBLog { 

static Connection con = null; 
    static PreparedStatement stmt = null; 

static { 
     try{ 
     new net.verizon.whatsnext.dblog.JDCConnectionDriver("oracle.jdbc.driver.OracleDriver", 
     "jdbc:oracle:thin:@localhost:7001:xe","user", "password"); 
    con=getConnection(); // Getting connection from Connection pool 

    }catch(Exception e){} 
    } 

public static Connection getConnection() throws SQLException { 
     return DriverManager.getConnection("jdbc:jdc:jdcpool"); 
    } 


public static void logService(String param1, String param2) { 
    ... 
    finally { 
       stmt.close(); 
      } 
    } 

public static void closeTrans() { 

    con.commit(); 
    con.close(); 
    } 
} //End of DBLog class 


public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) { 
    ... 
    finally { 
      DBLog.closeTrans(); 
     } 
    } 

그래서, 나는 마침내 doFilter 방법으로 블록에 커밋 한 후 마지막으로 연결을 종료하고 있습니다. 내가 제대로하고 있니? 작동할까요?

답변

1

먼저, 각각의 요청에 따라 연결을 여는 것이 아니라 연결 풀 (아마도 DataSource)에서 연결을 재사용하지 않는 것이 넣어 공유 공간에서 - 가장 쉬운 방법은 정적 인 ThreadLocal 필드를 활용하는 것입니다. 필터에서

:

public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) { 
    Connection conn = obtainConnection(); // obtain connection and store it ThreadLocal 
    conn.setAutoCommit(false); 
    try { 
    chain.doFilter(request, response); 
    } finally { 
    conn.commit(); 
    } 
} 

로거 클래스에서 : 일반적으로

public static void logService(String param1, String param2) { 
    Connection conn = getConnection(); // obtain thread-local connection 
    // your database statements go here 
} 

, 정적을 사용하지 마십시오. 로깅에 대한 접근 방식을 다시 고려해보십시오.

1

요청 당 트랜잭션 사용을 고려하십시오. 요청을 처리하기 전에 데이터베이스 트랜잭션을 열고 나중에 커밋하는 Filter을 만들 수 있습니다. 이것은 그것을 할 것입니다.

+0

보다 구체적인 plz 수 있습니다. –

+0

열 거래와 서블릿을 감싸는 것이다, 당신의 웹 응용 프로그램에 필터를 추가 공공 무효 doFilter (ServletRequest의 REQ, ServletResponse를의 RESP) { 시도 {여기 // 열려있는 트랜잭션 filterChain.doFilter (REQ, RESP) ; } finally { // 여기서 트랜잭션을 커밋하십시오. } } – ahanin

+0

괜찮습니다.하지만 plz는 doFilter를 커밋하는 방법을 제안합니다. 위의 게시물에서 자세한 내용을 추가했습니다. –

1

트랜잭션 경계는 보안 및 로깅의 경우처럼 코드의 장식으로 볼 수 있습니다.

은의 당신이 당신의 현재의 데이터베이스 작업에 의해 구현되고있는 하나의 인터페이스 BusinessTask, 있다고 가정 해 봅시다 : 예를 들어

public interface BusinessTask { 
    public void doWork(); 
} 

을, 당신은 AddSavingsAccountTaskTransferMoneyTask 있습니다.

처음에는 모든 작업을 개별적으로 커밋 (또는 롤백)하는 방식으로 구현할 수있었습니다. 그러나 계정을 만들고 즉시 돈을 송금하는 작업을 만들고 싶다면 거래 경계를 변경해야하기 때문에 문제가 발생할 수 있습니다.

이와 같은 방법으로 트랜잭션 구분을 배치 할 수있는 TransactionDecorator를 정의하는 것이 좋습니다.

public class TransactionDecorator implements BusinessTask{ 

    private final BusinessTask task; 

    public TransactionDecorator(BusinessTask task){ 
     this.task = task; 
    } 

    @Override 
    public void doWork() { 
     //beging transaction 
     task.doWork(); 
     //commit or rollback 
    } 
} 

그럼 당신은 단순히 트랜잭션 경계와 기존 작업을 장식 할 수 있습니다

final AddSavingsAccount addSavingsAccountTask = new AddSavingsAccount(); 
final TransferFunds transferFundsTask = new TransferFunds(); 

BusinessTask transaction = new TransactionDecorator(new BusinessTask(){ 

    @Override 
    public void doWork() { 
     addSavingsAccountTask.doWork(); 
     transferFundsTask.doWork(); 
    } 
}); 

transaction.doWork(); //all the magic happens here 

지금, 난 그냥 여기에 패턴을 제안하고있다. 이 코드의 구현은 코드 구조에 따라 디자인에 따라 다릅니다.

또한 참조

관련 문제