MySQLNonTransientConnectionException
作为Java小白,今天遇到了一个很神奇的东西,就是这串异常:
com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: No operations allowed after connection closed.
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:425)
at com.mysql.jdbc.Util.getInstance(Util.java:408)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:919)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498) ...............
今天捣鼓了好久,看了网上的一些解决方法对我来说好像没什么用😁,但是对你们来说可能有用。我自己的解决方法留在了最后,毕竟我是小白😁。
这个异常之所以会出现,是因为Mysql在5以后针对超长时间DB连接做了一个处理,那就是如果一个DB连接在无任何操作情况下过了8个小时后,Mysql会自动把这个连接关闭。所以使用连接池的时候虽然连接对象还在但是链接数据库的时候会一直报这个异常。同时不排除在多次进行数据库操作时,只进行了一次的数据库驱动连接的选择。在多次使用的时候会导致,一直使用那个,会导致一直没有对连接关闭(第三种解决方法)。
一、
第一种是在DB连接字符串后面加一个参数。这样的话,如果当前链接因为超时断掉了,那么驱动程序会自动重新连接数据库。
jdbc:mysql://localhost:3306/数据库名?autoReconnect=true
二、
Mysql 服务器默认的“wait_timeout”是8小时,也就是说一个connection空闲超过8个小时,Mysql将自动断开该connection。 这就是问题的所在,在C3P0 pools中的connections如果空闲超过8小时,mysql将其断开,而C3P0并不知道该connection已经失效,如果这时有 Client请求connection,C3P0将该失效的Connection提供给Client,将会造成上面的异常。
解决的方法有3种:
①增加wait_timeout的时间。
②减少Connection pools中connection的lifetime。
③测试Connection pools中connection的有效性。
三、这里是我出现的问题(Java小白,不喜勿喷)
问题代码:
static {
Properties properties = new Properties();
try {
properties.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("database.properties"));
//properties.load(new FileInputStream("./src/database.properties"));
driverClass = properties.getProperty("driver");
url = properties.getProperty("url");
user = properties.getProperty("user");
password = properties.getProperty("password");
conn = DriverManager.getConnection(url, user, password);
} catch (IOException | SQLException e) {
e.printStackTrace();
}
}
public static Connection getConnection() {
return conn;
}
修改后:
static {
Properties properties = new Properties();
try {
properties.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("database.properties"));
//properties.load(new FileInputStream("./src/database.properties"));
driverClass = properties.getProperty("driver");
url = properties.getProperty("url");
user = properties.getProperty("user");
password = properties.getProperty("password");
} catch (IOException e) {
e.printStackTrace();
}
}
public static Connection getConnection() {
try {
conn = DriverManager.getConnection(url, user, password);
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}