2012-04-05 1 views
1

私は、Java Weblogicポータルアプリケーションの特定の詳細をOracle DBに記録するためにデータベースログを実装しました。 このために、接続プーリングを使用して接続を取得し、jdbcを呼び出してストアドプロシージャを呼び出します。jdbc呼び出しで、一度にコミットを減らして一括レコードを挿入しますか?

私は接続オブジェクトを取得してSPを呼び出す静的JavaメソッドlogServiceを持っています。 このlogserviceメソッドは、Javaアプリケーションのさまざまな場所から呼び出され、関連する詳細がintでSPコールに渡されるパラメータで渡されます。

したがって、ポータルにアクセスする各ユーザーに約10-20のログサービスメソッド呼び出しがあります。 それで、私は10-20のSPコールを行い、私はSPを呼び出すたびにコミットしなければなりませんでした。

しかし、問題は、私のDBAは、コミット頻度が高いので、一度にすべてのトランザクションをコミットしないことをお勧めしています。 これはどのようにして達成できますか?明確でない場合は、サンプルコードを投稿できます。次のように

はい、私はすでに、次のように

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を呼び出しています、私のWebアプリケーション用に

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メソッドの中でfinally {}ブロックでトランザクションをコミットするにはどうすればよいですか?

フィルタのアプローチ -

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

開かれたトランザクションを使用してサーブレットを包むことになる、あなたのウェブ・アプリケーションにフィルタを追加: ます。public voidのdoFilter(ServletRequestのREQ、RESPたServletResponse){ 試し{ここ //開いているトランザクション 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 

は今、私はちょうどここにパターンを示唆しています。このコードの実装は、コードの構造に応じてデザインによって異なります。

さらに参照

関連する問題