MYSQL JDBC java.sql.SQLException: операция не разрешена после закрытия ResultSet

0

У меня есть программа, которая запрашивает базу данных с использованием разных драйверов jdbc. Эта ошибка специфична для драйвера MySQL.

Здесь основное изложение.

У меня есть еще один класс run-run query, который использует драйвер postgresql jdbc, который отлично работает. Обратите внимание на строку conn.close(); это отлично работает на моем postgresql query runner, но для этого SQL runner возникает ошибка.

Я удалил строку conn.close(); и этот код работает нормально, но со временем он накапливает спальные соединения в базе данных. Как я могу это исправить?

Новая реликвия - это стороннее приложение, в которое я подаю данные, если вы не знаете, что это такое, не беспокойтесь, что это не очень важно для этой ошибки.

ГЛАВНЫЙ КЛАСС

public class JavaPlugin {
public static void main(String[] args) {
    try {
        Runner runner = new Runner();
        runner.add(new MonitorAgentFactory());
        runner.setupAndRun(); // never returns
    }
    catch (ConfigurationException e) {
        System.err.println("ERROR: " + e.getMessage());
        System.exit(-1);
    }
    catch (Exception e) {
        System.err.println("ERROR: " + e.getMessage());
        System.exit(-1);
        }
    }
}

MYSQL QUERY RUNNER CLASS

import com.newrelic.metrics.publish.util.Logger;
import java.sql.DriverManager;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.ResultSet;
import java.sql.Statement;



public class MySQLQueryRunner {
    private static final Logger logger = Logger.getLogger(MySQLQueryRunner.class);
    private String connectionStr;
    private String username;
    private String password;


    public MySQLQueryRunner(String host, long port, String database, String username, String password) {
        this.connectionStr = "jdbc:mysql://" + host + ":" + port + "/" + database + "?useSSL=false";
        this.username = username;
        this.password = password;
    }


    private void logError(String message) {
        logger.error(new Object[]{message});
    }


    private void logDebugger(String message) {
        logger.debug(new Object[]{message});
    }


    private Connection establishConnection() {
        try {
            Class.forName("com.mysql.jdbc.Driver");

        } catch (ClassNotFoundException e) {
            logError("MySQL Driver could not be found");
            e.printStackTrace();
            return null;
        }
        Connection connection = null;
        try {
            connection = DriverManager.getConnection(connectionStr, username, password);
            logDebugger("Connection established: " + connectionStr + " using " + username);
        } catch (SQLException e) {
            logError("Connection Failed! Check output console");
            e.printStackTrace();
            return null;
        }
        return connection;
    }



    public ResultSet run(String query) {
        Connection conn = establishConnection();
        if (conn == null) {
            logError("Connection could not be established");
            return null;
        }
        try {
            Statement stmt = conn.createStatement();
            ResultSet rs = stmt.executeQuery(query);
            conn.close();
            return rs;
        } catch (SQLException e) {
            logError("Failed to collect data from database");
            e.printStackTrace();
            return null;
        }

    }
}

КЛАСС АГЕНТА

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Map;
import com.newrelic.metrics.publish.Agent;

public class LocalAgent extends Agent {
    private MySQLQueryRunner queryRunner;
    private String name;
    private Map<String, Object> thresholds;
    private int intervalDuration;
    private int intervalCount;

    public LocalAgent(String name, String host, long port, String database, String username, String password, Map<String, Object> thresholds, int intervalDuration) {
        super("com.mbt.local", "1.0.0");
        this.name = name;
        this.queryRunner = new MySQLQueryRunner(host, port, database, username, password);
        // this.eventPusher = new NewRelicEvent();
        this.thresholds = thresholds;
        this.intervalDuration = intervalDuration;
        this.intervalCount = 0;
    }

    /**
     * Description of query
     */
    private void eventTestOne() {
        String query = "select count(1) as jerky from information_schema.tables;";
        ResultSet rs = queryRunner.run(query);
        try {
            while (rs.next()) {
                NewRelicEvent event = new NewRelicEvent("localTestOne");
                event.add("jerky", rs.getInt("jerky"));
                event.push();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    /**
     * blah
     */
    private void eventTestTwo() {
        String query = "SELECT maxlen FROM information_schema.CHARACTER_SETS;";
        ResultSet rs = queryRunner.run(query);
        try {
            while (rs.next()) {
                NewRelicEvent event = new NewRelicEvent("localTestTwo");
                event.add("beef", rs.getString("maxlen"));
                event.push();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }


    @Override
    public void pollCycle() {
        if (this.intervalCount % this.intervalDuration == 0) {
            eventTestOne();
            eventTestTwo();
        this.intervalCount = 0;
        }
        // Always incrementing intervalCount, keeping track of poll cycles that have passed
        this.intervalCount++;
    }

    @Override
    public String getAgentName() {
        return this.name;
    }
}
  • 0
    Вы должны закрыть соединение в «окончательном блоке»
  • 0
    Я попытался переместить conn.close () в блок finally под моим блоком try, но он выдает точно такую же ошибку.
Теги:
arrays
jdbc
resultset

1 ответ

1

Проблема в том, что вы пытаетесь получить доступ к ResultSet после закрытия connection.

Вы должны открыть и закрыть соединение в методе, вызывающем run() таким образом, соединение будет открыто при доступе и прохождении через Resultset и закройте его в блоке finally вызывающего метода.

Еще лучше было бы, если вы можете просто выполнить цикл ResultSet в методе run() и добавить данные в object и вернуть object, таким образом вы можете закрыть его в блоке finally метода run().

  • 0
    Разве соединение не закрывается автоматически? У меня эта программа работает с интервалами, и каждую минуту она будет запрашивать из базы данных. Через 10 минут я все еще вижу менее 3 соединений от пользователя в MySQL Workbench.
  • 0
    Не уверен, что вы спрашиваете здесь. Помните, что вы не можете прочитать ResultSet после закрытия соединения.
Показать ещё 3 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню