mysql链接出现: No operations allowed after statement closed.

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mysql链接出现: 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推荐的,需要程序员手动处理异常。
[java] view plaincopyprint?
<span style="font-family:Microsoft YaHei;font-size:12px;">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));
</span>
参考技术A 这个没问题, 能帮忙解决一下的哦
能否看看wo 的网名的啊?帮忙搞定一下啊

com.mysql.cj.exceptions.ConnectionIsClosedException: No operations allowed after connection closed.

目录

一、功能背景

二、错误信息

三、相关代码

四、问题原因

四、解决办法

1、修改dbDriver

2、修改数据库配置

3、通过修改配置文件信息


一、功能背景

在SpringBoot项目中使用第三方数据库进行业务处理,需手动配置连接信息,手段创建连接进行操作第三方数据库。

二、错误信息

Caused by: com.mysql.cj.exceptions.ConnectionIsClosedException: 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.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:61)
	at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:105)
	at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:151)
	at com.mysql.cj.NativeSession.checkClosed(NativeSession.java:1171)
	at com.mysql.cj.jdbc.ConnectionImpl.checkClosed(ConnectionImpl.java:573)
	at com.mysql.cj.jdbc.ConnectionImpl.prepareStatement(ConnectionImpl.java:1595)
	... 96 common frames omitted

三、相关代码

public List<Map<String, Object>> getDetailData() throws Exception 
        String jdbcUrl = "jdbc:mysql://xxxxxxx:3306/demo";
        String driverName = "com.mysql.cj.jdbc.Driver";
        String username = "";
        String password = "";
        DBHelper dbHelper = new DBHelper(jdbcUrl, driverName, username, Base64.decodeStr(password));
        Connection connection = dbHelper.conn;
        if (ObjectUtil.isEmpty(connection)) 
            throw new Exception("数据库连接异常");
        
        String variablesSql = "show variables like 'lower_case_table_names'";
        // 预执行加载
        PreparedStatement pst = null;
        // 结果集
        ResultSet resultSet = null;
        List<Map<String, Object>> list = new ArrayList<>();
        try 
            pst = connection.prepareStatement(variablesSql);
            resultSet = pst.executeQuery();
            ResultSetMetaData rsmd = resultSet.getMetaData();
            int columnCount = rsmd.getColumnCount();
            while (resultSet.next()) 
                Map<String, Object> valueMap = new LinkedHashMap();
                for (int i = 1; i <= columnCount; i++) 
                    // 通过序号获取列名,起始值为1
                    String columnName = rsmd.getColumnLabel(i);
                    // 通过列名获取值
                    String columnValue = resultSet.getString(columnName);
                    valueMap.put(columnName, columnValue);
                
                list.add(valueMap);
            
         catch (Exception e) 
            log.error("关闭数据库连接,出现异常", e);
            throw new Exception("获取表信息,出现异常", e);
         finally 
            try 
                if (Objects.nonNull(resultSet)) 
                    resultSet.close();
                
                if (Objects.nonNull(pst)) 
                    pst.close();
                
                if (Objects.nonNull(connection)) 
                    connection.close();
                
             catch (Exception e) 
                log.error("关闭数据库连接,出现异常", e);
            
        
        return list;
    

四、问题原因

Mysql服务器默认的“wait_timeout”是8小时,也就是说一个connection空闲超过8个小时,Mysql将自动断开该connection。这就是问题的所在,在C3P0 pools中的connections如果空闲超过8小时,Mysql将其断开,而C3P0并不知道该connection已经失效,如果这时有Client请求connection,C3P0将该失效的Connection提供给Client,将会造成上面的异常。

四、解决办法

1、修改dbDriver

把spring.datasource.driverClassName修改为:com.mysql.jdbc.Driver

修改后代码为:

public List<Map<String, Object>> getDetailData() throws Exception 
        String jdbcUrl = "jdbc:mysql://xxxxxxx:3306/demo";
        String driverName = "com.mysql.jdbc.Driver";
        String username = "";
        String password = "";
        DBHelper dbHelper = new DBHelper(jdbcUrl, driverName, username, Base64.decodeStr(password));
        Connection connection = dbHelper.conn;
        if (ObjectUtil.isEmpty(connection)) 
            throw new Exception("数据库连接异常");
        
        String variablesSql = "show variables like 'lower_case_table_names'";
        // 预执行加载
        PreparedStatement pst = null;
        // 结果集
        ResultSet resultSet = null;
        List<Map<String, Object>> list = new ArrayList<>();
        try 
            pst = connection.prepareStatement(variablesSql);
            resultSet = pst.executeQuery();
            ResultSetMetaData rsmd = resultSet.getMetaData();
            int columnCount = rsmd.getColumnCount();
            while (resultSet.next()) 
                Map<String, Object> valueMap = new LinkedHashMap();
                for (int i = 1; i <= columnCount; i++) 
                    // 通过序号获取列名,起始值为1
                    String columnName = rsmd.getColumnLabel(i);
                    // 通过列名获取值
                    String columnValue = resultSet.getString(columnName);
                    valueMap.put(columnName, columnValue);
                
                list.add(valueMap);
            
         catch (Exception e) 
            log.error("关闭数据库连接,出现异常", e);
            throw new Exception("获取表信息,出现异常", e);
         finally 
            try 
                if (Objects.nonNull(resultSet)) 
                    resultSet.close();
                
                if (Objects.nonNull(pst)) 
                    pst.close();
                
                if (Objects.nonNull(connection)) 
                    connection.close();
                
             catch (Exception e) 
                log.error("关闭数据库连接,出现异常", e);
            
        
        return list;
    

2、修改数据库配置

修改服务端连接超时时间

show global variables like 'wait_timeout';

set global wait_timeout=172800;

3、通过修改配置文件信息

#连接池配置
spring.datasource.max-idle=10
spring.datasource.max-wait=10000
spring.datasource.min-idle=5
spring.datasource.initial-size=5
spring.datasource.validation-query=SELECT 1
spring.datasource.test-on-borrow=false
spring.datasource.test-while-idle=true
spring.datasource.time-between-eviction-runs-millis=18800

   配置datasource时需要配置相应的连接池参数,定是去检查连接的有效性,定时清理无效的连接。配置完重启服务即生效。

  注:第三种方案不适用本文章对应的功能,只是一种解决方案。

以上是关于mysql链接出现: No operations allowed after statement closed.的主要内容,如果未能解决你的问题,请参考以下文章

java连接mysql出现异常No operations allowed after connection closed,怎么破?

MySQLNonTransientConnectionException: No operations allowed after statement closed hibernate

mysql数据库连接不定时报错,no operations allowed...

Spring Boot连接MySQL长时间不连接后报错`com.mysql.cj.core.exceptions.ConnectionIsClosedException: No operations

com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: No operations allowed after co

com.mysql.cj.exceptions.ConnectionIsClosedException: No operations allowed after connection closed.