2

Tomcat JDBC 接続プールを使用するサーバー アプリケーションがあります。

これは、DataSource を作成するために使用するコードです。

PoolProperties connProperties = new PoolProperties();
connProperties.setUrl(resources.getProperty("db.url"));
connProperties.setDriverClassName(resources.getProperty("db.driver"));
connProperties.setUsername(resources.getProperty("db.user"));
connProperties.setPassword(resources.getProperty("db.password"));
connProperties.setJmxEnabled(true);
connProperties.setTestWhileIdle(false);
connProperties.setValidationQuery("SELECT 1");
connProperties.setTestOnReturn(false);
connProperties.setValidationInterval(30000);
connProperties.setTimeBetweenEvictionRunsMillis(30000);
connProperties.setMaxActive(500);
connProperties.setInitialSize(50);
connProperties.setMaxWait(10000);
connProperties.setRemoveAbandonedTimeout(60);
connProperties.setMinEvictableIdleTimeMillis(60000);
connProperties.setSuspectTimeout(60);
connProperties.setMaxIdle(50);
connProperties.setMinIdle(10);
connProperties.setLogAbandoned(false);
connProperties.setRemoveAbandoned(true);
connProperties.setJdbcInterceptors("org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;"+
"org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer");

dataSource = new DataSource();
dataSource.setPoolProperties(connProperties); 

次に、プールから接続を取得する方法があります

protected Connection getDbConnection() throws Exception
{
    dbConn = dataSource.getConnection();
    return dbConn;
}

ステートメントを実行するたびに、次のコードを呼び出します。

protected CallableStatement executeCSqlQuery(String sql) throws Exception
{
    CallableStatement cstmt;
    ResultSet rs = null;

    try {
        cstmt = getDbConnection().prepareCall(sql);     
        cstmt.execute();            
    } catch (SQLException e) {
        throw e;
    }

    return cstmt;
}

これは、前のコードへの呼び出しの例です。

try {
    cstmt = dbConnection.executeCSqlQuery(query);
    rs = cstmt.getResultSet();
} catch (Exception e) {
    // do smething
} finally {
    try {
        if (cstmt != null) {
            cstmt.close();
        }
        dbConnection.shutdown();
    } catch (Exception e) {
        // do something
    }
}

public void shutdown() {
    if (this.dbConn != null) 
        this.dbConn.close();
}

私が直面している問題は、X秒ごとにスレッドで呼び出しを実行すると、「ステートメントが閉じられました」という例外が時々発生することです。なぜこれが起こるのかわかりません。ドライバーのバグか、データベースへの接続に失敗した(別のサーバーで実行されている)可能性があると考えています。

私はアイデアがありません。私は何が欠けていますか?

代わりにc3p0接続プールを使用する必要がありますか?

4

3 に答える 3

2

私は2つのことに気づきます:

1) connProperties.setTestOnReturn(false); true に変更する必要があります。そうしないと、接続が有効であるとは限りません。また、無効なステートメントを受け取るまで通知が届かない場合があります。

2) ResultSetStatement、およびConnectionオブジェクトは常に閉じる必要があります。多くの定型文が含まれますが、静的な Close ユーティリティ メソッドを使用することもできます。

于 2013-11-09T21:51:37.957 に答える
1

1)protected CallableStatement executeCSqlQuery(String sql) throws Exception呼び出し可能なステートメントを返します。メソッド内で閉じた後に再度使用しようとすると、おそらくそのエラーが発生します。オブジェクトを閉じる前に、そのオブジェクトに関連するすべての処理を実行する必要があります。

2) 同じメソッドにはcatch(SQLException ){throw e}. そこで例外を処理するか、伝播したい場合は try-catch を削除します

3) コードの最後の部分でわかりrs = cstmt.getResultSet();ます。Peter にリンクした投稿を読んだように、取得した逆の順序でリソースを閉じることは常に良い習慣です。だからrs.close(); cstmt.close(); connection.close();。サンプルには含まれていませんが、閉じた後に ResultSet を返すと、1) で説明したのと同じ問題が発生します。

于 2013-11-08T13:11:57.170 に答える