0

非常に不十分な、大規模な webapp をクリーンアップしています。一度に全部は無理なので、小分けにしています。私がやりたいことの 1 つは、SQL ステートメントを受け取り、コレクションを返す関数を含むクラスを実装することです。私の計画は、Web アプリケーションの残りの部分に影響を与えずに、データベース フレームワークを探し回って、そのレイヤーを置き換えることができるようにすることです。

テンプレート スタイルのデータベース アクセス関数から ResultSet を返す際の大きな問題は、ResultSet を無効にしないと接続を閉じることができないことです。

この古いスタックオーバーフローの投稿で提案を見つけて興奮しました。

私はCachedRowSetで引用された記事を読みましたが、記事のどこで、その使用が大量の結果をそれ自体に詰め込むことによって多くの JVM メモリを吸い上げるという問題を引き起こす可能性があると述べているかが心配です。

代替の Apache ResultSetDynaClassやその他のコレクションにも同じ問題はありませんか? 結果は何らかの方法でメモリに書き込まれる必要があります。右?

ChaedRowSet、ResultSetDynaClass、または Java Collection を使用して ResultSet データを保存した場合、ResultSet を閉じるとそのデータは失われますか?

HashMaps を使用して、一般的なデータベース クエリ関数から単一のレコードを格納しました。

コードが煩雑になることなく、Java Collections を使用して複数のレコードを保存するにはどうすればよいですか? できると仮定すると、他の 2 つのオプションよりもリソース効率や柔軟性に優れているでしょうか?

情報やアイデアをお寄せいただきありがとうございます。

4

1 に答える 1

1

これはWebアプリであるため、結果セットをいつ閉じる必要があるかがわかります。リクエストの最後です。結果セット/接続をリクエストスコープに登録し、リクエストの最後にそれらをすべて閉じることができます。これがColdFusion(Java上で実行)がそれを処理する方法です。

または、Mynaのように実行して、デフォルトで「マテリアライズド」コレクションを返すか、生の結果セットに対して実行されるオプションの行ハンドラーを使用することができます。2番目のケースでは、ほとんどの場合特別な処理を必要とし、コレクションに詰め込むだけでは実用的ではないBLOBなどに直接アクセスできます。また、rowHandlerがいつ実行されるかがわかっているため、結果セット/接続を閉じることができます。

アップデート:

これは、リクエスト終了時に閉じるアプローチの簡単な例です。

public class Query {
    static public ConcurrentHashMap     openResultSets  = new java.util.concurrent.ConcurrentHashMap();
    public ResultSet runQuery(String sql) throws SQLException{
        //set up connection, run query
        ResultSet rs = statement.executeQuery();
        if (Query.openResults.get(Thread.currentThread().getId()) == null){
            Query.openResults.put(Thread.currentThread().getId(),new Vector())
        }
        Vector openRS =  (Vector) Query.openResults.get(Thread.currentThread().getId()) 

        openRs.add(rs);
        return rs;
    }
    public void onRequestEnd(String sql) {
        Vector openRS =  (Vector) Query.openResults.get(Thread.currentThread().getId());
        if (openRS != null){
            for (ResultSet rs : openRS.values()){
                try{
                    rs.close();
                } catch(Exception e){}
            }
        }
        //do any other request end cleanup of connections, etc
    }
}

//in your servlet
public class Query extends HttpServlet {

    public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException{

        ResultSet rs = Query.runQuery("select * from AWESOME");
        //do awesome stuff, maybe load other classes that can run runQuery 

        Query.onRequestEnd();
    }
}

これは理想的ではありませんが、使用しているフレームワークがわかりません。setAttribute()/ getAttribute()を介してこれをHttpServletRequestオブジェクトに保持することはおそらく理にかなっていますが、それを使用するすべてのメソッドに要求を渡す必要があります。どちらの方法でも、開いている結果セットの配列を保持し、リクエストの最後にそれらを閉じる必要があります。ある種のフレームワークを使用すると、これが非常に簡単になります。

于 2012-04-26T18:20:51.487 に答える