【トラブル】【Java】JDBC ドライバ絡みのトラブル

【1】「SEVERE: A web application registered the JDBC driver...」が表示される

* Tomcatのログを見たら、Tomcat終了時に以下の「エラー内容」が表示された

エラー内容

SEVERE: A web application registered the JDBC driver [com.mysql.jdbc.Driver]
 but failed to unregister it when the web application was stopped.
To prevent a memory leak, the JDBC Driver has been forcibly unregistered.

発生環境

* OS : CentOS7
* Tomcat : Tomcat8.5
* Java :JDK1.8

解決案

* システム終了後(※)に、以下の「サンプル」の
 処理(DriverManager.deregisterDriver())を行う

サンプル

Enumeration<Driver> drivers = DriverManager.getDrivers();
while (drivers.hasMoreElements()) {
    Driver driver = drivers.nextElement();
    try {
        DriverManager.deregisterDriver(driver);
        System.out.println(String.format("deregistering jdbc driver: %s", driver));
    } catch (SQLException ex) {
        System.out.println(String.format("Error deregistering driver %s", driver));
        ex.printStackTrace();
    }

}

※補足:システム終了後について

Tomcatであれば、ServletContextListener.contextDestroyed 内で行う。

参考文献
https://stackoverflow.com/questions/3320400/to-prevent-a-memory-leak-the-jdbc-driver-has-been-forcibly-unregistered
http://d.hatena.ne.jp/muimy/20100918/1284812424

【2】「SQLException: No suitable driver found for...」が表示される

* 【1】とは、別のシステムの単体試験時に、以下の「エラー内容」が表示された

* 単体テストクラスには、3つのテストメソッドがあり、結果は以下の通り。
  + 1つ目は、問題なし
  + 2・3つ目のメソッドは、以下の「エラー内容」

* ネットにある「JDBCドライバがない」「Class.forName()を呼び出す」「DBのURLの指定が誤っている」は
   調査した結果、問題なかった(仮にこれらが原因の場合、1つのメソッドが問題なかった説明ができない)
 ~~~~~~~
  // ダメだった
  @Before
  public void setUp() throws Exception {
      Class.forName("com.mysql.jdbc.Driver");
  }
 ~~~~~~~

エラー内容

java.sql.SQLException: No suitable driver found for jdbc:mysql://localhost:3306/dbname

発生環境

* OS : CentOS7
* Java :JDK1.8
* JUnit : JUnit4

原因

* 【1】の「解決案」のコードを1つ目の最後に呼び出され、
 以降の単体試験に影響してしまっていた。

解決案

* JUnitの場合、@AfterClassのタイミングで、
 【1】の「解決案」のコードを呼び出すようにする
 ~~~~~~~
  @AfterClass
  public static void tearDownAfterClass() throws Exception {
     // このタイミングで、【1】の「解決案」のコードを呼び出すようにする
  }
 ~~~~~~~

 => 【後日談】JUnitを一気に実行すると、
 エラーになるのでJUnitに関しては呼び出さないのも手。

関連記事

MySQLJDBCドライバを v5.1.X から v8.0.X に上げたらエラー「The server time zone value」になる