MySQLNonTransientConnectionException: No operations allowed after statement closed
之所以會出現這個異常,是因為Mysql在5以後針對超長時間DB串連做了一個處理,那就是如果一個DB串連在無任何操作情況下過了8個小時後,Mysql會自動把這個串連關閉。所以使用串連池的時候雖然連線物件還在但是連結資料庫的時候會一直報這個異常。解決方案很簡單在Mysql的官方網站上就可以找到。
有兩個方法,
第一種是在DB連接字串後面加一個參數。
這樣的話,如果當前連結因為逾時斷掉了,那麼驅動程式會自動重新串連資料庫。
jdbc:mysql://localhost:3306/makhtutat?autoReconnect=true
不過Mysql並不建議使用這個方法。因為第一個DB操作失敗的後,第二DB成功前如果出現了重新串連的效果。這個失敗操作將不會處於一個事務以內,第二DB操作如果成功的話,這個事務將被提交。
conn.createStatement().execute( "UPDATE checking_account SET balance = balance - 1000.00 WHERE customer='Smith'");conn.createStatement().execute( "UPDATE savings_account SET balance = balance + 1000.00 WHERE customer='Smith'");conn.commit();
當然如果出現了重新串連,一些使用者變數和暫存資料表的資訊也會丟失。
另一種方法是Mysql推薦的,需要程式員手動處理異常。
public void doBusinessOp() throws SQLException { Connection conn = null; Statement stmt = null; ResultSet rs = null; int retryCount = 5; boolean transactionCompleted = false; do { try { conn = getConnection(); // assume getting this from a // javax.sql.DataSource, or the // java.sql.DriverManager conn.setAutoCommit(false); retryCount = 0; stmt = conn.createStatement(); String query = "SELECT foo FROM bar ORDER BY baz"; rs = stmt.executeQuery(query); while (rs.next()) { } all.close() transactionCompleted = true; } catch (SQLException sqlEx) { String sqlState = sqlEx.getSQLState(); // 這個08S01就是這個異常的sql狀態。單獨處理手動重新連結就可以了。 if ("08S01".equals(sqlState) || "40001".equals(sqlState)) { retryCount--; } else { retryCount = 0; } } finally { all close: } } while (!transactionCompleted && (retryCount > 0));}}