У меня есть программа, которая запрашивает базу данных с использованием разных драйверов 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;
}
}
Проблема в том, что вы пытаетесь получить доступ к ResultSet
после закрытия connection
.
Вы должны открыть и закрыть соединение в методе, вызывающем run()
таким образом, соединение будет открыто при доступе и прохождении через Resultset
и закройте его в блоке finally
вызывающего метода.
Еще лучше было бы, если вы можете просто выполнить цикл ResultSet
в методе run()
и добавить данные в object
и вернуть object
, таким образом вы можете закрыть его в блоке finally
метода run()
.