他の人が述べたように、あなたのコードは基本的には正しいですが、外側try
は不要です。ここにいくつかの考えがあります。
DataSource
ここでの他の答えは、正しいと良いです受け入れ答え bpgergoによります。しかし、最近のJavaでのDataSource
使用よりも一般的に推奨されるの使用を示しているものはありませんDriverManager
。
したがって、完全を期すために、データベースサーバーから現在の日付をフェッチする完全な例を次に示します。ここで使用されているデータベースはPostgresです。他のデータベースも同様に機能します。の使用を、データベースorg.postgresql.ds.PGSimpleDataSource
にDataSource
適したの実装に置き換えます。特定のドライバー、またはそのルートをたどると接続プールによって実装が提供される可能性があります。
DataSource
実装は必要はありません、それは「開かれていない」んので、閉鎖されます。A DataSource
はリソースではなく、データベースに接続されていないため、データベースサーバー上のネットワーク接続もリソースも保持していません。A DataSource
は、データベースへの接続を確立するときに必要な情報であり、データベースサーバーのネットワーク名またはアドレス、ユーザー名、ユーザーパスワード、および最終的に接続を確立するときに指定するさまざまなオプションが含まれます。したがって、DataSource
実装オブジェクトは、try-with-resources括弧内には入りません。
ネストされたtry-with-resources
コードはネストされたtry-with-resourcesステートメントを適切に使用します。
以下のサンプルコードでは、try-with-resources構文を2回使用していることにも注意してください。外部try
は2つのリソースを定義します:Connection
とPreparedStatement
。内部try
はResultSet
リソースを定義します。これは一般的なコード構造です。
例外が内部の例外からスローされ、そこでキャッチされない場合、ResultSet
リソースは自動的に閉じられます(存在する場合、nullではありません)。その後、PreparedStatement
が閉じられ、最後にConnection
が閉じられます。リソースは、try-with-resourceステートメント内で宣言された逆の順序で自動的に閉じられます。
ここのサンプルコードは非常に単純化されています。書かれているように、1つのtry-with-resourcesステートメントで実行できます。しかし、実際の作業では、ネストされたtry
呼び出しのペアの間でより多くの作業を行う可能性があります。たとえば、ユーザーインターフェイスまたはPOJOから値を抽出?
し、PreparedStatement::set…
メソッドへの呼び出しを介してSQL内のプレースホルダーを満たすためにそれらを渡す場合があります。
構文メモ
末尾のセミコロン
try-with-resourcesの括弧内の最後のリソースステートメントの後のセミコロンはオプションであることに注意してください。私は2つの理由で自分の作業にそれを含めています。一貫性と完全に見えること、および行末のセミコロンを気にすることなく、行の組み合わせをコピーして貼り付けることが容易になります。IDEは最後のセミコロンに不必要なフラグを立てることがありますが、そのままにしても問題はありません。
Java 9 – try-with-resourcesで既存の変数を使用する
Java 9の新機能は、try-with-resources構文の拡張です。これで、try
ステートメントの括弧の外側にリソースを宣言してデータを追加できます。私はまだこれがJDBCリソースに役立つとは思っていませんが、あなた自身の仕事でそれを覚えておいてください。
ResultSet
閉じますが、閉じない場合があります
理想的な世界でResultSet
は、ドキュメンテーションが約束するように、それ自体が閉じます。
ResultSetオブジェクトは、それを生成したStatementオブジェクトが閉じられるか、再実行されるか、複数の結果のシーケンスから次の結果を取得するために使用されると、自動的に閉じられます。
残念ながら、過去に一部のJDBCドライバーは悪名高くこの約束を果たせなかった。その結果、多くのJDBCプログラマは、明示的に近いすべてのJDBCリソースを含むことを学んだConnection
、PreparedStatement
とResultSet
あまりにも。最新のtry-with-resources構文により、コードがよりコンパクトになり、操作が簡単になりました。Javaのチームはマーキングの気に行ったことをお知らせResultSet
としてAutoCloseable
、私たちはそれを使用することをお勧めします。すべてのJDBCリソースの周りにtry-with-resourcesを使用すると、コードの意図がより自己文書化されます。
コード例
package work.basil.example;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.time.LocalDate;
import java.util.Objects;
public class App
{
public static void main ( String[] args )
{
App app = new App();
app.doIt();
}
private void doIt ( )
{
System.out.println( "Hello World!" );
org.postgresql.ds.PGSimpleDataSource dataSource = new org.postgresql.ds.PGSimpleDataSource();
dataSource.setServerName( "1.2.3.4" );
dataSource.setPortNumber( 5432 );
dataSource.setDatabaseName( "example_db_" );
dataSource.setUser( "scott" );
dataSource.setPassword( "tiger" );
dataSource.setApplicationName( "ExampleApp" );
System.out.println( "INFO - Attempting to connect to database: " );
if ( Objects.nonNull( dataSource ) )
{
String sql = "SELECT CURRENT_DATE ;";
try (
Connection conn = dataSource.getConnection() ;
PreparedStatement ps = conn.prepareStatement( sql ) ;
)
{
… make `PreparedStatement::set…` calls here.
try (
ResultSet rs = ps.executeQuery() ;
)
{
if ( rs.next() )
{
LocalDate ld = rs.getObject( 1 , LocalDate.class );
System.out.println( "INFO - date is " + ld );
}
}
}
catch ( SQLException e )
{
e.printStackTrace();
}
}
System.out.println( "INFO - all done." );
}
}
try (ResultSet rs = ps.executeQuery()) {
ため、内部は必要ありません