MySQLNonTransientConnectionException: No operations allowed after statement closed
之所以會出現這個異常,是因爲Mysql在5以後針對超長時間DB連接做了一個處理,那就是如果一個DB連接在無任何操作情況下過了8個小時後,Mysql會自動把這個連接關閉。所以使用連接池的時候雖然連接對象還在但是鏈接數據庫的時候會一直報這個異常。解決方法很簡單在Mysql的官方網站上就可以找到。
有兩個方法,
第一種是在DB連接字符串後面加一個參數。
這樣的話,如果當前鏈接因爲超時斷掉了,那麼驅動程序會自動重新連接數據庫。
不過Mysql並不建議使用這個方法。因爲第一個DB操作失敗的後,第二DB成功前如果出現了重新連接的效果。這個失敗操作將不會處於一個事務以內,第二DB操作如果成功的話,這個事務將被提交。jdbc:mysql://localhost:3306/makhtutat?autoReconnect=true
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));}
}