2016-07-15 7 views
0

スタンドアロン(Java以外のWebアプリケーション)のJavaアプリケーションで接続プールを使用する必要があります。私が働いているところでは、セキュリティのレイヤーを経由せずにAPIを使用することは許されず、仕事はすぐに完了する必要があります。以下は、この接続プールを作成する私の試みです。スタンドアロンJavaアプリケーションで接続プールを作成する

私はこのコードをテストし、アプリケーション全体のコンテキスト内で何百回もテストしましたが、すべてのケースでエラーがゼロでテストされました。さらに、各実行のパフォーマンスは、単純な接続は、データを取得し、シリアルアプローチで切断します。しかし、私はまだこのアプローチで問題が起きる可能性があることを懸念しています。私は単にまだ発掘していません。私は以下のコードに関して誰かが持っているアドバイスを感謝します。これはこのサイトの最初の投稿です。私がエチケットで間違いを犯した場合は、私に知らせてください。私はこのサイトを投稿する前にこのサイトを検索しました。呼び出しの例については、以下のコードを参照してください。ありがとう。 --JR

package mypackage; 

import java.sql.Connection; 
import java.sql.SQLException; 
import java.util.Map; 
import java.util.concurrent.ArrayBlockingQueue; 
import java.util.concurrent.BlockingQueue; 
import java.util.concurrent.TimeUnit; 

/** 
* Note: This class is only instantiated once per application run. 
*  Multiple instantiations, as specified in the release notes, 
*  are not supported.  
*/ 
public class ConnectionManager { 

    // Use a blocking queue to store the database connections. 
    // The application will only be called once, by a single user, 
    // but within the application many threads will require 
    // a connection. 
    private BlockingQueue<Connection> connectionQueue = null; 

    // Load the connection queue with a user-defined number of connections. 
    // Params contains a map of all non hard-coded variables in the 
    // application. 
    public ConnectionManager(int howMany, Map<String, Object> params) { 
     Database database = new Database(); 
     connectionQueue = new ArrayBlockingQueue<Connection>(howMany); 
     for(int i = 0; i < howMany; i++) { 
      connectionQueue.add(database.getConn(params)); 
     } 
    } 

    // Return a connection from the queue, waiting up to 15 minutes to do so. 
    // 15 minutes is hard-coded because it is the standard time-out for all 
    // processes at our agency. This application must complete in less 
    // than fifteen minutes (is currently completing in thirty five seconds). 
    public Connection getConnection() { 
     Connection conn = null; 
     try { 
      conn = connectionQueue.poll(15, TimeUnit.MINUTES); 
     } 
     catch(InterruptedException e) { 
      e.printStackTrace(); 
     } 
     catch(SQLException e) { 
      e.printStackTrace(); 
     } 
     return conn; 
    } 

    // Returns a connection to the connection queue. 
    public void returnConnectionToManager(Connection conn) { 
     connectionQueue.add(conn); 
    } 

    // Called on the last line of the application program's dispatcher. 
    // Closes all active connections (which will only exist if there 
    // was a failure within one of the worker threads). 
    public void closeAllConnections() { 
     for(Connection conn : connectionQueue) { 
      try { 
       conn.close(); 
      } 
      catch(SQLException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 
} 

呼び出し例:

...

private ConnectionManager cm; 

...

public Table(Map<String, Object> params, String method) { 
    ... 
    cm = (ConnectionManager) params.get("cm"); 
} 

// Execute a chunk of SQL code without requiring processing of a 
// result set. Acquires connection from pool via cm.getConnection 
// and releases connection via cm.returnConnectionToManager. 
// (Database is just a helper class with simple methods for 
// closing prepared statement, result sets, etc.) 
private void execute(String sql) { 
    PreparedStatement ps = null; 
    Connection conn = null; 
    try { 
    conn = cm.getConnection(); 
    ps = conn.prepareStatement(sql); 
    ps.execute(); 
    } 
    catch (SQLException e) { 
    e.printStackTrace(); 
    } 
    finally { 
    database.closePreparedStatement(ps); 
    cm.returnConnectionToManager(conn); 
    } 
} 
+1

ストアオブジェクトシングルトンクラスまたは列挙型の中へ。 Prefarably enum。このようにして、接続プールに簡単にアクセスでき、複数のオブジェクトを簡単に回避できます。 DBトランザクションでアプリケーションコードが終了した後、個別の接続を解放するメソッドを追加します。 – Acewin

+3

'私が働いているところでは、セキュリティのレイヤーを経由せずにAPIを使用することは許されません。何千人もの人が試してテストしたオープンソースのフレームワークよりも社内コードが安全だと考える人がいることは、常に驚きです。 –

+0

独自のコードを書くのではなく、IMOでAPIをクリアするほうが良いでしょう – Acewin

答えて

0

あなたのコードはよさそうだが、1つの重大な問題があり、そのAPIのクライアントは接続の取得と解放を処理する必要があり、そのうちの1つは忘れてしまい、メモリ/リソースのリークが発生する可能性があります。

実行するクエリーを投稿する場所を1つ作成します。ここで接続し、クエリを実行してプールに接続を返します。接続が返されることを保証します。単一の接続で複数の照会を1つずつ呼び出す必要がある場合は、メソッドが順序または実行するSQL照会の配列またはリストを受け入れるようにします。アイデアは各リクエストをdbにカプセル化して、すべての接続を管理することです。あなたが実装する必要があるen execute(Connection conn)を持つインターフェイスを作成する必要はありません。そのようなオブジェクトを取るいくつかのサービスが接続を確立し、リソースを接続プールに戻すことができます。 のような何か:使用の

interface SqlWork { 
execute(Connection conn); 
} 

SqlWork myWork = new SqlWork() { 
    execute(Connection conn) { 
    // do you work with the conn here 
    } 
} 

class SqlExecutionService { 
    ConnectionManager cm = ...; 

    public void execute(SqlWork sqlWork) { 
     Connection conn = null; 
     try { 
     conn = cm.getConnection(); 
     sqlWork.execute(conn); 
     } catch (Your exceptions here) { 
     //serve or rethrow them 
     } 
     finally 
     { 
     if (conn!=null) { 
      cm.returnConnectionToManager(conn); 
     } 
     } 
    } 
} 

例:

SqlExecutionService sqlExecService = ...; 
sqlExecService.execute(myWork); 
+0

ありがとう、Krzysztof。私が言及しなかったことの1つは、誰もこのコードを使用しないということです。彼らはそれを実行することしか許されません。だから私はそれを悪用する人を心配する必要はありません。それが間違って実行されているだけです(その場合は問題が発生しますが、それは悪いと思いますが、私が働く場所のようなものです - 誰もが自分を守る必要があります。コードとあなたの洞察をお寄せいただきありがとうございます。とても有難い。 – Jack

+0

それは有効な点です:)私は、この承認が将来あなたの時間を節約することを保証します。私はそれが自動でない場合、何かをすることを忘れることがよくあります。 –

関連する問題