1

私はjspを使い始めたばかりで、私の質問はこれです-シングルトンクラスがある場合、その後どのように片付けますか?

特に:

public class DBConnection {
  private static Connection connection = null;
  private static Statement statement = null;

  public static ResultSet executeQuery(String query){
    if (connection == null) { /*initConnection*/ }
    if (statement == null) { /*initStatement*/ }

    // do some stuff
  }
}

現在、このクラスをいくつかのページで使用して、jdbc から結果を取得しています。ただし、最終的に呼び出す必要がありますstatement.close();-connection.close();いつそれらを呼び出す必要がありますか?

クエリを作成する必要があるたびにデータベースへの接続を何度も呼び出すのは間違っていると感じたため、シングルトンを使用しています。

4

3 に答える 3

1

常にConnection閉じている必要があり、必要な操作のすべてのデータベース ステートメントを実行した後。2 つの例:

ケース 1: データベースからの基準でフィルター処理された製品のリストをユーザーに表示する必要があります。解決策: 接続を取得し、フィルター基準を使用して製品のリストを取得し、接続を閉じます。

ケース 2: クライアントはこれらの製品のいくつかを選択し、最小在庫を更新してアラートを受け取り、在庫を補充します。解決策: 接続を取得し、すべての製品を更新して、接続を閉じます。

これらのケースに基づいて、多くのことを学ぶことができます。

  • 単一の接続を開いている/維持しながら、複数のステートメントを実行できます。
  • 接続は、それが使用されるブロックにのみ存在する必要があります。その前後に生きるべきではありません。
  • マルチスレッド環境であるため、両方のケースが同時に発生する可能性があります。そのため、結果の問題を回避するために、1 つのデータベース接続を 2 つのスレッドで同時に使用できるようにしてはなりません。たとえば、ユーザー A が Foo カテゴリの商品を検索し、ユーザー B が Bar カテゴリの商品を検索した場合、Bar カテゴリの商品をユーザー A に表示したくありません。
  • 最後の文から、各データベース操作 (またはケース 2 のような同様の操作のグループ) は、アトミック操作で処理する必要があります。これを保証するには、接続をシングルトン オブジェクトに格納してはならず、メソッド内でのみ有効にする必要があります。使用されています。

結果として:

  • Connectionthe nor the Statementnor the ResultSetnor other JDBC リソースを として宣言しないでくださいstatic。それは単に失敗します。代わりに、クラスのConnectionas フィールドのみを宣言してください。DBConnection各メソッドに、各Statement(またはPreparedStatement)ResultSetおよび特定の JDBC リソースの処理を決定させます。
  • 使用後に接続を閉じる必要があるため、さらに 2 つのメソッドを追加します:void open()void close(). これらのメソッドは、データベース接続の取得とその接続のクローズを処理します。
  • さらに、 はクラスおよびデータベース接続操作DBConnectionのラッパー クラスのように見えるためConnection、少なくとも 3 つのメソッドを追加することをお勧めします: void setAutoCommit(boolean autoCommit)void commit()およびvoid rollback(). これらのメソッドは、それぞれ と の単純なラッパーになります。Connection#setAutoCommit Connection#closeConnection#rollback

次に、この方法でクラスを使用できます。

public List<Product> getProducts(String categoryName) {
    String sql = "SELECT id, name FROM Product WHERE categoryName = ?";
    List<Product> productList = new ArrayList<Product>();
    DBConnection dbConnection = new DBConnection();
    try {
        dbConnection.open();
        ResultSet resultSet = dbConnection.executeSelect(sql, categoryName); //execute select and apply parameters
        //fill productList...
    } catch (Exception e) {
        //always handle your exceptions
        ...
    } finally {
        //don't forget to also close other resources here like ResultSet...
        //always close the connection
        dbConnection.close();
    }
}

この例でPreparedStatementは、 はメソッド内になく、getProductsメソッドのローカル変数になることに注意してくださいexecuteSelect

その他の注意事項:

  • アプリケーション サーバーで作業している場合は、単純に を使用するなどして接続を開くのではなくClass.forName("...")、データベース接続プールを使用してください。ここで説明されているように、C3P​​0 などのいくつかのデータベース接続プール ライブラリを使用できます: JDBC で接続プールを確立する方法? . または、ここで説明するように、アプリケーション サーバーで構成します: Is it a good idea to put jdbc connection code in servlet class?
  • これが学習目的である場合は、データベースとの通信を処理する独自のクラスを作成します。実際のアプリケーションでは、これは推奨されません (実行してはいけないという意味ではありません)。代わりに、JPA (Java 公式 ORM フレームワーク) やHibernateなどの ORM などのデータベース接続フレームワークを使用します。Spring JDBCMyBatisのようなデータベース通信を処理する ORM フレームワークはありません。選択はあなた次第です。

より詳しい情報:

于 2013-10-16T19:45:38.917 に答える
0

クラスに 2 つのメソッドを追加します。

public static void open() throws SomeException;
public static void close() throws SomeException;

呼び出しコードは次のようになります{

try {
    DBConnection.open();
    ... code to use the connection one or more times ...
} finally {
    DBConnection.close();
}

その中にすべてのデータベース呼び出しをラップすると、例外がスローされたかどうかに関係なく、閉じられます。

もちろん、これは私がお勧めする通常のクラスと大差ありません。

try {
    DBConnection conn = new DBConnection();
    conn.open();

    ... all the code to use the database (but you pass 'conn' around) ...

} finally {
    conn.close();
}

を見て、 java.lang.AutoCloseableそれ java.io.Closeableが役立つかどうかを確認することもできます。

2

ページがロードされても開いたままにしておくと、何かを置く場所がないtry ... finallyため、サーブレットが閉じたり、サーバーが閉じたりするときに開いたり閉じたりできます。

開いたままにする場合は、見ていないときに閉じないことを確認するコードを追加する必要があります。たとえば、短いネットワーク障害により、ネットワークが閉じられる可能性があります。その場合、閉じたときに再度開く必要があります。そうしないと、その時点からのすべてのデータベース アクセスが失敗します。

データベース プールの概念を調べることができます。Apache には DBCP があります。Tomcat には独自の機能があり、非常に優れています。JBOSS、WebSphere、WebLogic などの他のコンテナにはすべてそれらがあります。Spring Framework で使用できるものがいくつかあります。それが行うことは、1 つ以上のデータベース接続を管理することです。あなたのコードはそれを要求し、何も利用できない場合を除き、開いているものを返し、それを開いて返します。コードがそれを通過したときに呼び出しcloseますが、実際には接続を閉じず、プールに返すだけです。

通常は、シャットダウンされた接続を確認し、必要に応じて再開するようにプールを構成できます。

于 2013-10-16T19:03:25.190 に答える