0

Apache Tomcat で Axis2 を使用しています。Web サービスのクライアントがデータベースにクエリを実行できるようにする必要があるため、Tomcat のコンテキストに次のリソースを追加すると、接続プールが自動的に作成されることをインターネットで見つけました。

リソース名="jdbc/TestDB" auth="コンテナ"
               type="javax.sql.DataSource"
               removeAbandoned="true"
               removeAbandonedTimeout="30"
               maxActive="80"   
               maxIdle="30"
               maxWait="10000"
               ユーザー名="ユーザー"
               パスワード=""
               driverClassName="org.postgresql.Driver"
               URL = "jdbc:postgresql://localhost:5432/mydb"
               useUnicode="true"
               characterEncoding="utf-8"
               characterSetResults="utf8"
               validationQuery="/* ping */ SELECT 1"

うまくいっているようですが、今度は同じ PreparedStatement を再利用したいので、クライアントがリクエストを行うたびに解析されるわけではありません。そのため、PreparedStatement をすべてのクライアント接続に対して静的にし、それを作成するときに、statement.setPoolable(true) を呼び出します。これは、私が理解していることから、冗長です (PreparedStatement は既にプール可能です)。このように、PreparedStatement が単一の接続に結び付けられないことを願っていました。それでも、次のエラーが表示されます。

java.sql.SQLException: アドレス * の org.apache.tomcat.dbcp.dbcp.DelegatingPreparedStatement が閉じられています。

奇妙なことに、セットを作成する前に statement.isClosed() を呼び出すと、false が返されます。次に、何かを設定すると、その例外がスローされます。

コードは次のとおりです。

try {
        Connection conn;

        Context envCtx = (Context) new InitialContext().lookup("java:comp/env");

        DataSource ds = (DataSource) envCtx.lookup("jdbc/TestDB");
        conn = ds.getConnection();    

        if(statement == null){
        //statement is static, so it won't be null at the second call                
            statement = conn.prepareStatement(query);
            statement.setPoolable(true);        
        }
        if(statement.isClosed()){
            statement = conn.prepareStatement(query);
            //it never gets here
        }
        else{
            Logger.getLogger(HelloAxisWorld.class.getName()).log(Level.INFO, "STATEMENT IS NOT CLOSED", new Object());  
            //it always gets here
        }

        statement.setString(1, par1); //here, the second call throws an exception
        ResultSet rs = statement.executeQuery();
        while (rs.next()) {
            cur_value = rs.getInt("cur_value");
        }         
        rs.close();

        conn.close();

    }catch (Exception ex) {            
        Logger.getLogger(HelloAxisWorld.class.getName()).log(Level.SEVERE, null, ex);          
    }

statement.isClosed が false を返す理由がわかりませんが、例外はそれが閉じていると言っています。多分これはpreparedStatementを再利用する方法ではありませんが、どうすればそれを行うことができますか? 同じクエリで conn.prepareStatement を呼び出すと、jdbc はキャッシュから PreparedStatement を返します (再度解析されることはありません) と読みましたが、それが正しいかどうかはわかりません。

4

1 に答える 1

0

あなたが抱えているケースの1つを処理するために特別に作成されたc3p0と呼ばれるプロジェクトがあります。Web サイトはこちらhttps://sourceforge.net/projects/c3p0/およびこちらhttp://www.mchange.com/projects/c3p0/データソース JNDI バインディング、接続プーリング、およびステートメント プーリングを処理します。このライブラリをサーブレットで使用している人のスタックオーバーフローに関するリファレンスもあります

于 2012-10-18T07:31:17.137 に答える