起きたこと
Java7から採用されたtry-with-resources文を使用してSQLのストアド呼び出しをしようとしたときにエラーが発生した。
環境
OS
Windows 10
JavaVersion
jdk-15.0.2
JDBC
sqljdbc_9.2
SQL Server
2019
エラーになったコード
public Connection calltest() {
String connectionUrl = "jdbc:sqlserver://localhost:1433;"
+"databaseName=TESTDB;"
+"user=TestUser;"
+"password=*******;"
try (Connection connection= DriverManager.getConnection(connectionUrl)){
return connection;
}catch (SQLException e) {
e.printStackTrace();
}
return null;
}
sqlcall call = new sqlcall();
con = call.calltest();
cs = con.prepareCall("{call dbo.sp_TESTA(?,?)}");
エラーメッセージ
com.microsoft.sqlserver.jdbc.SQLServerException: 接続は閉じられています。 at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDriverError(SQLServerException.java:234) at com.microsoft.sqlserver.jdbc.SQLServerConnection.checkClosed(SQLServerConnection.java:1217) at com.microsoft.sqlserver.jdbc.SQLServerConnection.prepareCall(SQLServerConnection.java:3808) at com.microsoft.sqlserver.jdbc.SQLServerConnection.prepareCall(SQLServerConnection.java:3416)
原因
公式に以下のように記載されていました。
次の例ではtry-with-resources文を使用して、java.sql.Statementオブジェクトを自動的に閉じます。
public static void viewTable(Connection con) throws SQLException {
String query = "select COF_NAME, SUP_ID, PRICE, SALES, TOTAL from COFFEES";
try (Statement stmt = con.createStatement()) {
ResultSet rs = stmt.executeQuery(query);
while (rs.next()) {
String coffeeName = rs.getString("COF_NAME");
int supplierID = rs.getInt("SUP_ID");
float price = rs.getFloat("PRICE");
int sales = rs.getInt("SALES");
int total = rs.getInt("TOTAL");
System.out.println(coffeeName + ", " + supplierID + ", " + price +
", " + sales + ", " + total);
}
} catch (SQLException e) {
JDBCTutorialUtilities.printSQLException(e);
}
}
try-with-resources文のメリットである自動でclose処理を行ってくれるという部分を知らずに
Connectionタイムアウトを疑って接続周りについて調査に時間を取られました。
まとめ
Connection処理を各classで呼び出す際にはとても便利ですが、共通処理として使おうとしたときは
少し考えないといけないかもしれません。
今回はtry-with-resources文を使用しないようにして回避しました。