お試し環境
- Java8
- PostgreSQL9.6
- Windows10 Pro
Connection#isClosedがtrueになるタイミングが気になった。
CommonsDBCP使ってコネクションプールし、DBサーバ再起動した場合に
プールしているコネクションはもう使えない。
この時、Connection#isClosedはtrue返すよね?っていうのを試した。
まず、Javadocでは以下のように記載されている。
この
Connection
オブジェクトがクローズされているかどうかを取得します。接続は、close
メソッドが呼び出されるか、特定の致命的エラーが発生した場合にクローズされます。このメソッドは、Connection.close
メソッドが呼び出されたあとに呼び出された場合にだけtrue
を返すことが保証されています。このメソッドは通常、データベースへの接続が有効か無効かを判定するために呼び出すことはできません。一般のクライアントでは、操作を実行したときにスローされる例外をキャッチすることにより、接続が無効であると判定します。
Connection#closeを明示的に呼び出すとtrue返すけど、他はエラー出たときにtrueを返すかもって言っています。
でだ。エラー処理を書く時に上記のタイミングでtrueを返してくれればいいなと思って試した。
もちろんこれはJDBC?DBCP?実装依存なので全てのDB(OracleとかMySQL)でそうなるとは言い切れないので参考程度に。
やりたいことはコネクションプールからコネクション取得→途中でDBサーバ再起動でコネクションが無効な状態→Connection#isClosedの状態確認
結果としてはisClosedがtrueになりました。
以下、ソースとか
- Maven
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-dbcp2 --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-dbcp2</artifactId> <version>2.1.1</version> </dependency> <!-- https://mvnrepository.com/artifact/org.postgresql/postgresql --> <dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> <version>42.1.4</version> </dependency> <!-- https://mvnrepository.com/artifact/commons-dbutils/commons-dbutils --> <dependency> <groupId>commons-dbutils</groupId> <artifactId>commons-dbutils</artifactId> <version>1.7</version> </dependency>
- DBCP
driverClassName=org.postgresql.Driver url=jdbc:postgresql://localhost:5433/test username=postgres password=postgres validationQuery=select 1 maxWait=1000 initialSize=3 maxActive=3 maxIdle=3
- App.java
package test.dbcp.connection;
import java.io.InputStream; import java.sql.Connection; import java.sql.SQLException; import java.util.List; import java.util.Map; import java.util.Properties;
import javax.sql.DataSource;
import org.apache.commons.dbcp2.BasicDataSourceFactory; import org.apache.commons.dbutils.DbUtils; import org.apache.commons.dbutils.QueryRunner; import org.apache.commons.dbutils.ResultSetHandler; import org.apache.commons.dbutils.handlers.MapListHandler;
public class App { public static void main( String[] args ) { try { QueryRunner runner = new QueryRunner();
Properties properties = new Properties(); InputStream is = ClassLoader.getSystemResourceAsStream("dbcp.properties"); properties.load(is); DataSource ds = BasicDataSourceFactory.createDataSource(properties);
ResultSetHandler<List<Map<String, Object>>> resultSet = new MapListHandler(); Connection con = null; for (int i = 0; i < 100; i++) {
// ループしている最中にPostgresのサービスを停止→開始を行う try { con = ds.getConnection(); List<Map<String, Object>> ret = runner.query(con, "select * from batch_history", resultSet); System.out.println(ret.size()); } catch (SQLException e) { e.printStackTrace(); } finally { System.out.println(con.isClosed()); DbUtils.closeQuietly(con); } Thread.sleep(500); } } catch (Exception e) { e.printStackTrace(); } } }
コメント