Когда мое приложение теряет соединение, как мне его восстановить?
У меня есть приложение, которое я подключаю к базе данных MySQL. Он теряет связь в середине ночи, а затем извергает null
Соединения и JDBC не получили сообщения в течение X секунд.
Я звоню getConnection()
прежде чем делать что-либо, что требует связи с сервером SQL.
Это мое getConnection()
метод:
private Connection getConnection() {
try {
if (connection != null) {
if (connection.isClosed() || !connection.isValid(10000)) {
this.initializeRamsesConnection();
}
} else {
this.initializeRamsesConnection();
}
} catch (Exception e) {
debug("Connection failed: " + e);
}
return connection;
}
в initializeRamsesConnection()
Метод Я помещаю пароль и так далее информацию в строку, а затем я создаю соединение стандартным способом JDBC.
Затем я называю этот метод:
private Connection getConnectionFromConnectionString() {
Connection con = null;
String driver = "com.mysql.jdbc.Driver";
try {
Class.forName(driver);//jdbc sorcery
//if there is no connection string
if (getConnectionString() == null) {
HMIDatabaseAdapter.debug("No connection string");
}
//makes a string out of the values of db/host
String str = getConnectionString();
//if there is no driver
if (driver == null) {
debug("" + ": " + "No driver");
}
//Tries to make a connection from the connection string, username, and the password.
con = DriverManager.getConnection(str, username, password);
//if for some reason the connection is null
if (con == null) {
HMIDatabaseAdapter.debug("CONNECTION IS NULL, WHAT?");
}
} catch (Exception ex) {
HMIDatabaseAdapter.debug("getConnection() " + ex);
}
return con;
}
Что я могу изменить в любом из этих способов, чтобы приспособиться к потере соединения?
3 ответа
Это не правильный способ получения соединения. Вы извлекаете соединение и назначаете его в качестве экземпляра (или, что еще хуже, статической) переменной класса. По сути, вы сохраняете соединение открытым навсегда и повторно используете одно соединение для всех запросов. Это может привести к катастрофе, если запросы выполняются разными потоками. Кроме того, когда он остается открытым слишком долго, БД восстанавливает его, потому что предполагает, что он мертв / протек.
Вы должны приобрести и закрыть соединение в кратчайшие сроки. Т.е. в том же самом try
блок, где вы выполняете запрос. Что-то вроде этого:
public Entity find(Long id) throws SQLException {
Entity entity = null;
try (
Connection connection = dataSource.getConnection(); // This should return a NEW connection!
PreparedStatement statement = connection.prepareStatement(SQL_FIND);
) {
statement.setLong(1, id);
try (ResultSet resultSet = preparedStatement.executeQuery()) {
if (resultSet.next()) {
entity = new Entity(
resultSet.getLong("id"),
resultSet.getString("name"),
resultSet.getInt("value")
);
}
}
}
return entity;
}
Если вы беспокоитесь о производительности соединения и хотите повторно использовать соединения, то вам следует использовать пул соединений. Вы могли бы доморощить один, но я настоятельно не одобряю это, поскольку вы, кажется, довольно плохо знакомы с материалом. Просто используйте существующий пул соединений, такой как BoneCP, C3P0 или DBCP. Обратите внимание, что вы не должны изменять идиому JDBC, как показано в примере выше. Вам все еще нужно приобрести и закрыть соединение в кратчайшие сроки. Пул соединений сам по себе будет беспокоиться о повторном использовании, тестировании и / или закрытии соединения.
Смотрите также:
Откуда в вашем коде возникают ошибки при потере соединения? Это, вероятно, будет лучшим местом для начала.
Сверху головы (и я могу ошибаться) соединения JDBC закроются только при реальной фатальной ошибке, поэтому вы не будете знать, что они потерпели неудачу, пока не попытаетесь что-то сделать.
В прошлом я делал недействительным соединение в точке сбоя и периодически повторял попытку.
Может быть, это то, что вы ищете: http://dev.mysql.com/doc/refman/5.0/en/auto-reconnect.html
Для Java см. AutoReconnect: http://dev.mysql.com/doc/refman/5.0/en/connector-j-reference-configuration-properties.html