使用javaSE连接mysql,无论是直接使用jdbc连接还是使用mybatis,运行一段时间后,都有如下两个异常:
No operations allowed after connection closed
或
CommunicationsException: Communications link failure The last packet successfully received from the server was 53,159 milliseconds ago. The last packet sent successfully to the server was 0 milliseconds ago.
无论是修改连接后的参数例如增加autoReconnect=true或者useSLL=false都无效,直接修改mysql的基本配置比如连接的超时时间也是不可取的,因为如果使用的是客户的mysql,自己使用方式不恰当还要给人家硬改配置也只是以开发者思维去做项目而不是客户角度。
解决办法就是使用阿里的druid数据库连接池,让连接池自己去维护连接,包括重连机制,druid都会自己根据配置去做维护。
上代码:
第一步:获取druid数据源
/**
* 获取druid数据源
*
* @return
* @throws SQLException
*/
public static DruidDataSource getDefaultMysqlDataSource() throws SQLException {
String mysqlUrl = "";
String username = "";
String password = "";
String driverClass = "";
//jdbc配置
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName(driverClass);
dataSource.setUrl(mysqlUrl);
dataSource.setUsername(username);
dataSource.setPassword(password);
//连接池配置
dataSource.setMaxActive(20);
dataSource.setMinIdle(1);
dataSource.setInitialSize(1);
dataSource.setMaxWait(60000);
dataSource.setKeepAlive(true);
dataSource.setTimeBetweenEvictionRunsMillis(10000);
dataSource.setMinEvictableIdleTimeMillis(300000);
dataSource.setMaxEvictableIdleTimeMillis(600000);
dataSource.setTestWhileIdle(true);
dataSource.setTestOnBorrow(false);
dataSource.setTestOnReturn(false);
dataSource.setValidationQuery("SELECT 'x'");
dataSource.setPoolPreparedStatements(true);
dataSource.setMaxPoolPreparedStatementPerConnectionSize(20);
dataSource.setFilters("stat");
return dataSource;
}
第二步:直接使用数据源获取连接并操作数据库
/**
* 非常重要的提示:
* 注意:连接每次使用完请关闭,否则会导致连接一直存在并被占用,新的请求到来,会创建新的连接,
* 等连接达到数据库连接的最大值,新请求就无法被处理。这里把连接关闭后,连接会还给druid连接池,
* 新的请求到来,会复用这个连接。
*/
try (DruidPooledConnection connection = defaultMysqlDataSource.getConnection()){
String sql = "insert into sub1 (id, message, status, result, exectime) " +
" values(?, ?, ?, ?, NOW())";
PreparedStatement ps = connection.prepareStatement(sql);
ps.setString(1, log.getSubUri());
ps.setString(2, log.getMessage());
ps.setString(3, log.getStatus());
ps.setString(4, log.getResult());
ps.executeUpdate();
} catch (SQLException e) {
logger.error("插入日志失败", e);
}