2

私が恐れているのは、Java での接続プーリングを理解する上で根本的な問題を抱えているのではないかということです。

IDBCDataSource を接続プールとして使用しています。アプリケーションのエントリ ポイントで、たとえば setMaxActive=50 で BasicDataSource をインスタンス化します。その DataSource のインスタンスは、いくつかのビジネス ロジックによって利用されるさまざまな DAO に渡されます。

各 DAO は getConnection() を呼び出しますが、呼び出される close() は 1 つもありません。私の推測では、DAO が使用されなくなった後、ガベージ コレクターが接続を閉じます。

私の問題は、常に接続が不足していることです (つまり、利用可能な接続を待っているコード)。

ここで、各データベース操作の最後に close() 呼び出しを追加するとします。スローされた例外で何が起こるか。DAO ですべての例外をキャッチする必要があります。必ず接続を閉じてから、発生した例外を再スローしてください。

- 現在のアプローチ:

public class MyDAO {
     private Connection con;

     public MyDAO (DataSource ds) {
          con = ds.getConnection();     
     }     

     public MyReturnClass execSomeQuery() throws SQLException {
          String sql = String.format("SELECT * FROM foo");
          PreparedStatement ps = con.prepareStatement(sql);
          ResultSet rs = ps.executeQuery();

          while (rs.next()) {
               …     
               ...
          }          

          return result;
     }
}


public class MyAppLogic() {
     DataSource ds; 

     public MyAppLogic(DataSource ds) {
          this.ds = ds;
     }

     public void doSomeStuff() {
          MyDAO myDAO = MyDAO(ds);
          myDAO.execSomeQuery();
     }
}
4

2 に答える 2

2

close接続が接続プールに返されるようにする必要があります。GC はあなたの接続を閉じません!

于 2012-12-15T20:24:45.447 に答える
2

各メソッドでロジックを複製する必要がないように、接続を管理するラッパーまたは親クラスを作成できます。以下に例を示します (実際にこれをコンパイルまたはテストしていないことに注意してください)。

public interface DAOClass {
    public void execSomeQuery() throws SQLException;
}

public class MyDAOWrapper {
    private DAOClass dao;
    private DataSource ds;

    public MyDAOWrapper(DataSource ds, DAOClass dao) {
        this.dao = dao;
        this.ds = ds;
    }

    public void exec() throws SQLException {
        Connection con = ds.getConnection();
        try {
            dao.execSomeQuery();
        }
        finally {
            con.close();
        }
    }

}

// usage
    public void doSomeStuff() throws SQLException {
        MyDAOWrapper dao = new MyDAOWrapper(ds, new MyDAO());
        dao.exec();
    }

エラー処理に関しては、キャッチしない限り例外を再スローする必要はありません。あなたのfinally句は接続を閉じる必要があり(存在する場合)、それが終了すると、例外は伝播し続けます。

try {
  do_something();
}
finally {
  cleanup();
  // throw is not necessary
}
于 2012-12-15T20:45:31.030 に答える