Java JDBC MySQL 异常:“ResultSet 关闭后不允许操作" [英] Java JDBC MySQL exception: "Operation not allowed after ResultSet closed"
问题描述
我已经为此工作了将近一天半,但似乎无法解决此错误.我不知道为什么 ResultSet 被关闭.也许你们中的一些人可以帮助我.
I've been working at this for almost a day and a half now and I can't seem to work this error out. I don't know why the ResultSet is being closed. Maybe some of you can help me out.
MySQL 数据库:
package net.gielinor.network.sql;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public abstract class MySQLDatabase {
private String host;
private String database;
private String username;
private String password;
private Connection connection = null;
private Statement statement;
public MySQLDatabase(String host, String database, String username, String password) {
this.host = host;
this.database = database;
this.username = username;
this.password = password;
}
public abstract void cycle() throws SQLException;
public abstract void ping();
public void connect() {
try {
Class.forName("com.mysql.jdbc.Driver").newInstance();
connection = DriverManager.getConnection(String.format("jdbc:mysql://%s/%s", host, database), username, password);
statement = connection.createStatement();
} catch (Exception e) {
e.printStackTrace();
}
}
public void ping(String table, String variable) {
try {
statement.executeQuery(String.format("SELECT * FROM `%s` WHERE `%s` = 'null'", table, variable));
} catch (Exception e) {
connect();
}
}
public ResultSet query(String query) throws SQLException {
if (query.toLowerCase().startsWith("select")) {
return statement.executeQuery(query);
} else {
statement.executeUpdate(query);
}
return null;
}
public Connection getConnection() {
return connection;
}
}
MySQLHandler
MySQLHandler
package net.gielinor.network.sql;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import net.gielinor.network.sql.impl.MySQLDonation;
public class MySQLHandler extends Thread {
private static final MySQLHandler mysqlHandler = new MySQLHandler();
public static MySQLHandler getMySQLHandler() {
return mysqlHandler;
}
private static List<MySQLDatabase> updateList;
private static String host;
private static String database;
private static String username;
private static String password;
@Override
public void run() {
while (true) {
for (MySQLDatabase database : updateList) {
try {
if (database.getConnection() == null) {
database.connect();
} else {
database.ping();
}
database.cycle();
} catch (Exception ex) {
ex.printStackTrace();
}
try {
Thread.sleep(10000);
} catch (Exception ex) {
}
}
}
}
private static void loadProperties() {
Properties p = new Properties();
try {
p.load(new FileInputStream("./sql.ini"));
host = p.getProperty("host");
database = p.getProperty("database");
username = p.getProperty("username");
password = p.getProperty("password");
} catch (Exception ex) {
System.out.println("Error loading MySQL properties.");
}
}
public static String getHost() {
return host;
}
static {
loadProperties();
updateList = new ArrayList<MySQLDatabase>();
updateList.add(new MySQLDonation(host, database, username, password));
}
}
MySQL 捐赠
package net.gielinor.network.sql.impl;
import java.sql.ResultSet;
import java.sql.SQLException;
import net.gielinor.game.model.player.Client;
import net.gielinor.game.model.player.PlayerHandler;
import net.gielinor.game.model.player.PlayerSave;
import net.gielinor.network.sql.MySQLDatabase;
public final class MySQLDonation extends MySQLDatabase {
public MySQLDonation(String host, String database, String username, String password) {
super(host, database, username, password);
}
@Override
public void cycle() throws SQLException {
ResultSet results = query("SELECT * FROM `gieli436_purchases`.`donations`");
if (results == null) {
return;
}
while (results.next()) {
String username = results.getString("username").replace("_", " ");
System.out.println("name=" + username);
Client client = (Client) PlayerHandler.getPlayer(username.toLowerCase());
System.out.println(client == null);
if (client != null && !client.disconnected) {
int creditamount = results.getInt("creditamount");
if (creditamount <= 0) {
continue;
}
handleDonation(client, creditamount);
query(String.format("DELETE FROM `gieli436_purchases`.`donations` WHERE `donations`.`username`='%s' LIMIT 1", client.playerName.replaceAll(" ", "_")));
}
}
}
@Override
public void ping() {
super.ping("donations", "username");
}
private void handleDonation(Client client, int creditamount) throws SQLException {
client.credits = (client.credits + creditamount);
client.sendMessage("Thank you for your purchase. You have received " + creditamount + " store credits.");
PlayerSave.save(client);
}
}
这里发生异常:在 MySQLDonation 的 while 循环中,实际的堆栈跟踪是这样的:
The exception occurs here: in the while loop within MySQLDonation and the actual stacktrace is this:
java.sql.SQLException: Operation not allowed after ResultSet closed
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1055)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:956)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:926)
at com.mysql.jdbc.ResultSetImpl.checkClosed(ResultSetImpl.java:794)
at com.mysql.jdbc.ResultSetImpl.next(ResultSetImpl.java:7077)
at net.gielinor.network.sql.impl.MySQLDonation.cycle(Unknown Source)
at net.gielinor.network.sql.MySQLHandler.run(Unknown Source)
有了这些信息,让我说这确实有效,我收到了我的消息以及游戏中没有的内容,但它会重复,就像用户永远不会从查询中删除一样,因此它给了他们无限的奖励.如果您需要更多信息,请随时询问.
With this information let me say that this does work, I get my message and what not in-game but it repeats, like the user is never removed from the query so it gives them infinite rewards. If you need any more information feel free to ask.
推荐答案
当您运行 Delete
查询时,您使用与 Delete
相同的 Statement
>选择查询.当您在同一个 Statement
上重新执行时,之前的 ResultSet
会关闭.
When you run the Delete
query, you use the same Statement
that was used in the Select
query. When you re-execute on the same Statement
, the previous ResultSet
gets closed.
为避免这种情况,您应该在每次执行查询时创建一个新的 Statement
.所以把statement = connection.createStatement();
从MySQLDatabase
类中的connect()
方法中删除,并替换所有statement
code> 到 connection.createStatement()
.您也可以选择完全删除私有变量statement
.
To avoid this, you should create a new Statement
everytime you execute a query. So remove statement = connection.createStatement();
from the connect()
method in MySQLDatabase
class, and replace all statement
in that class to connection.createStatement()
. You may also choose to delete the private variable statement
altogether.
您可以在此处阅读更多相关信息.
这篇关于Java JDBC MySQL 异常:“ResultSet 关闭后不允许操作"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!