简体   繁体   English

获取玩家统计信息时,MySQLNonTransientConnectionException

[英]MySQLNonTransientConnectionException when getting player stats

I'm storing player stats for my minigame in a SQL database and I'm getting the following error while loading stats: 我将迷你游戏的玩家统计信息存储在SQL数据库中,并且在加载统计信息时出现以下错误:

com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: No operations allowed after connection closed.
[23:37:09] [Server thread/WARN]:    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
[23:37:09] [Server thread/WARN]:    at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
[23:37:09] [Server thread/WARN]:    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
[23:37:09] [Server thread/WARN]:    at java.lang.reflect.Constructor.newInstance(Unknown Source)
[23:37:09] [Server thread/WARN]:    at com.mysql.jdbc.Util.handleNewInstance(Util.java:425)
[23:37:09] [Server thread/WARN]:    at com.mysql.jdbc.Util.getInstance(Util.java:408)
[23:37:09] [Server thread/WARN]:    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:918)
[23:37:09] [Server thread/WARN]:    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:897)
[23:37:09] [Server thread/WARN]:    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:886)
[23:37:09] [Server thread/WARN]:    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:860)
[23:37:09] [Server thread/WARN]:    at com.mysql.jdbc.ConnectionImpl.throwConnectionClosedException(ConnectionImpl.java:1187)
[23:37:09] [Server thread/WARN]:    at com.mysql.jdbc.ConnectionImpl.checkClosed(ConnectionImpl.java:1182)
[23:37:09] [Server thread/WARN]:    at com.mysql.jdbc.ConnectionImpl.prepareStatement(ConnectionImpl.java:4035)
[23:37:09] [Server thread/WARN]:    at com.mysql.jdbc.ConnectionImpl.prepareStatement(ConnectionImpl.java:4004)

Code: 码:

public void loadPlayer(Player p) {
    if (!isPlayerInDataBase(p)) {
        Bukkit.getScheduler().runTaskAsynchronously(Main.getInstance(), new Runnable() {
            @Override
            public void run() {
                try (Connection connection = sqlConnection.c) {
                    PreparedStatement insert = connection.prepareStatement(
                            "INSERT INTO `MurderData` (uuid, wins, deaths, loses, kills, score) VALUES (?, ?, ?, ?, ?, ?)");
                    insert.setString(1, p.getUniqueId().toString());
                    insert.setInt(2, 0);
                    insert.setInt(3, 0);
                    insert.setInt(4, 0);
                    insert.setInt(5, 0);
                    insert.setInt(6, 0);
                    insert.execute();
                    ClosePreparedStatement(insert);
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        });
    }

    if (isPlayerInDataBase(p)) {
        Bukkit.getScheduler().runTaskAsynchronously(Main.getInstance(), new Runnable() {
            @Override
            public void run() {
                try (Connection connection = sqlConnection.c;
                     PreparedStatement select = connection.prepareStatement(
                             "SELECT * FROM `MurderData` WHERE uuid='" + p.getUniqueId().toString() + "'")) {
                    ResultSet result = select.executeQuery();
                    if (result.next()) {
                        if (getPlayerData(p) != null) {
                            getPlayerData(p).adddeaths(result.getInt("deaths"));
                            getPlayerData(p).addkill(result.getInt("kills"));
                            getPlayerData(p).addwins(result.getInt("wins"));
                            getPlayerData(p).addlose(result.getInt("loses"));
                            getPlayerData(p).addscore(result.getInt("score"));
                        }
                        CloseResultSet(result);
                    }
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        });
    }
}

The error at this code: 此代码处的错误:

PreparedStatement select = connection.prepareStatement(
                        "SELECT * FROM `MurderData` WHERE uuid='" + p.getUniqueId().toString() + "'")) {

Full code: 完整代码:

public boolean isPlayerInDataBase(Player p) {
    try (Connection connection = sqlConnection.c;
         PreparedStatement select = connection.prepareStatement(
                 "SELECT * FROM `MurderData` WHERE uuid='" + p.getUniqueId().toString() + "'")) {
        ResultSet result = select.executeQuery();
        if (result.next()) {
            result.close();
            return true;
        }
    } catch (SQLException e) {
        e.printStackTrace();
    }
    return false;
}

Side question: should I close the result set and prepared statements after completing the process? 附带问题:完成流程后,我应该关闭结果集和准备好的语句吗? And should I do that instantly or with a delay? 我应该立即还是延迟执行此操作?

It seems that you have taken the try-with-resources statement from some other code without understanding what it does. 看来您是从其他代码中获取了try-with-resources语句,但并不了解它的作用。 From that link: 从该链接:

The try-with-resources statement is a try statement that declares one or more resources. try-with-resources语句是一个try语句,用于声明一个或多个资源。 A resource is an object that must be closed after the program is finished with it. 资源是程序完成后必须关闭的对象。 The try-with-resources statement ensures that each resource is closed at the end of the statement. try-with-resources语句可确保在语句末尾关闭每个资源。 Any object that implements java.lang.AutoCloseable, which includes all objects which implement java.io.Closeable, can be used as a resource. 任何实现java.lang.AutoCloseable的对象(包括所有实现java.io.Closeable的对象)都可以用作资源。

In other words, when you use the syntax 换句话说,当您使用语法时

try (Connection connection = sqlConnection.c) {
     // ...
}

You are implicitly calling close() on sqlConnection.c , which is not assigned to again. 您正在隐式调用sqlConnection.c上的close() ,该连接未再次分配给它。 Therefore, the next time you try to query your database from this connection, it is still closed, so you get this error. 因此,下次尝试从该连接查询数据库时,它仍处于关闭状态,因此会出现此错误。

A simple fix would be to move the declaration of local variable connection out of the try-with-resources statement so it does not get closed at the end of the method. 一个简单的解决方法是将局部变量connection的声明从try-with-resources语句中移出,这样它就不会在方法结束时被关闭。 You should also look at where you use the try-with-resources syntax elsewhere in your program and make sure you're not closing anything you don't want to close. 您还应该查看程序中其他地方使用try-with-resources语法的位置,并确保不关闭任何您不想关闭的内容。

This is the fixed version of your code (from the pastebin you linked in a comment): 这是代码的固定版本(来自在注释中链接的pastebin ):

public boolean isPlayerInDataBase(Player p) {
    Connection connection = sql.getConnection();
    try (PreparedStatement select = connection.prepareStatement(
            "SELECT * FROM `MurderData` WHERE uuid='" + p.getUniqueId().toString() + "'")) {

        ResultSet result = select.executeQuery();
        if (result.next()) {
            CloseResultSet(result);
            return true;
        }
    } catch (SQLException e) {
        e.printStackTrace();
    }
    return false;
}

Additionally, in your loadPlayer() method, you can replace the two if statements with this: 此外,在您的loadPlayer()方法中,您可以将两个if语句替换为:

if (isPlayerInDataBase(p)) {
    // code if player is in database
} else {
    // code if player is not in database
}

The problem is that your isPlayerInDataBase call closes the connection. 问题是您的isPlayerInDataBase调用关闭了连接。 And in the line where your error occurs, you are using that same connection that you closed. 在发生错误的那一行中,您使用的是您关闭的连接相同的连接

This is why you are getting the error you see, because you are attempting to perform a database operation after the connection is closed. 这就是为什么看到错误的原因,因为您在关闭连接后尝试执行数据库操作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 插入/获取数据时,MySQL中的MySQLNonTransientConnectionException - MySQLNonTransientConnectionException in mySQL when inserting / getting data 尝试与IP地址连接时,Java JDBC:MySQLNonTransientConnectionException - Java JDBC: MySQLNonTransientConnectionException when trying to connect with IP address 这样更新玩家统计资料是个好主意吗? - Is it good idea to update player stats like this? com.mysql.jdbc.exceptions.MySQLNonTransientConnectionException:当autocommit = true时无法调用回滚 - com.mysql.jdbc.exceptions.MySQLNonTransientConnectionException: Can't call rollback when autocommit=true 来自ColdFusion应用程序的MySQLNonTransientConnectionException - MySQLNonTransientConnectionException from ColdFusion application Java/GlassFish MySQLNonTransientConnectionException - Java/GlassFish MySQLNonTransientConnectionException GlassFish Server部署和MySQLNonTransientConnectionException - GlassFish Server deployment and MySQLNonTransientConnectionException MySQLNonTransientConnectionException:连接太多 - MySQLNonTransientConnectionException: Too many connections 运行时JDBC程序中的MySQLNonTransientConnectionException - MySQLNonTransientConnectionException in JDBC program at run time Tomcat日历Web应用mysql:MySQLNonTransientConnectionException: - Tomcat Calendar Webapp mysql: MySQLNonTransientConnectionException:
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM